gpt4 book ai didi

r - 使用 data.table 的兄弟网络

转载 作者:行者123 更新时间:2023-12-01 01:25:49 27 4
gpt4 key购买 nike

我想使用 data.table 创建一个兄弟网络.

我的数据是这样的

indata <-
structure(list(id = c(1L, 2L, 3L, 4L, 12L, 13L, 14L, 15L), fid = c(NA,
9L, 1L, 1L, 7L, 5L, 5L, 5L), mid = c(0L, NA, 2L, 2L, 6L, 6L,
6L, 8L)), .Names = c("id", "fid", "mid"), class = "data.frame", row.names =
c(NA, -8L))

这是

  id fid mid
1 1 NA 0
2 2 9 NA
3 3 1 2
4 4 1 2
5 12 7 6
6 13 5 6
7 14 5 6
8 15 5 8

三列分别代表id,父亲的id,母亲的id。 0NA表示不可用。因此,在上面的数据中,人 3 和 4 是同胞 sibling (他们都有父亲 1 和母亲 2 ),而 12 和 13 是半 sibling (他们有不同的父亲但同一个母亲, 6 )。

对于数据框中的每一行,我想要一个该人的 sibling 列表(让我们先考虑同父异母的 sibling )。我理想的最终结果是

  id fid mid sibs
1 1 NA 0 NA
2 2 9 NA NA
3 3 1 2 4
4 4 1 2 3
5 12 7 6 13, 14
6 13 5 6 12, 14, 15
7 14 5 6 12, 13, 15
8 15 5 8 13, 14

最后一列,sibs , 是一个列表或向量(它不一定是数据集的一部分)。

下面给出了使用基数 R 获取输出的粗略版本

# get a list of offspring for each father id
foffspring <- by(indata, indata$fid, function(i) { i$id }, simplify=FALSE)
# and mother id
moffspring <- by(indata, indata$mid, function(i) { i$id }, simplify=FALSE)

让 sibling 遍历每个id。找到他们的父亲和母亲,并结合前面列表中的两个相关条目

sibs <- sapply( 1:nrow(indata), function(i) {
res <- c()
if( !is.na(indata$fid[i]) )
res <- c(res, unlist(foffspring[paste0(indata$fid[i])]))
if( !is.na(indata$mid[i]) )
res <- c(res, unlist(moffspring[paste0(indata$mid[i])]))
unique(res[res != indata$id[i]])
}, simplify=TRUE )

这产生

> sibs
[[1]]
integer(0)

[[2]]
integer(0)

[[3]]
[1] 4

[[4]]
[1] 3

[[5]]
[1] 13 14

[[6]]
[1] 14 15 12

[[7]]
[1] 13 15 12

[[8]]
[1] 13 14

这是期望的输出。现在上面的代码既不快也不漂亮,我真的很想看看我是否能得到一个花哨的 data.table版本。然而,我的data.table -fu 似乎缺少。

library(data.table)
DT <- data.table(indata)
# Create lists with the _indices_ of the offsprings
FT <- DT[ , list( yidx = list(.I) ) , by = fid ]
MT <- DT[ , list( yidx = list(.I) ) , by = mid ]

MT看起来像这样

   mid  yidx
1: NA 2
2: 0 1
3: 2 3,4
4: 6 5,6,7
5: 8 8

一模一样moffspring上面除了它包含索引而不是标签。然而,这并不是真正的问题。然后我想将表格合并在一起

setkey(DT, fid)
setkey(FT, fid)
setkey(MT, mid)

# Inner join
P1 <- DT[FT]

# And inner join on mother
setkey(P1, mid)
P1[MT]

现在最终结果是这样的

   id fid mid  yidx i.yidx
1: 2 9 NA 2 2
2: 1 NA 0 1 1
3: 3 1 2 3,4 3,4
4: 4 1 2 3,4 3,4
5: 13 5 6 6,7,8 5,6,7
6: 14 5 6 6,7,8 5,6,7
7: 12 7 6 5 5,6,7
8: 15 5 8 6,7,8 8

差不多了。现在,如果我采用 yidx 的行联合和 i.yidx然后我得到同父异母的列表(包括本人),按行的交集将产生完整的 sibling 。请注意,此处的索引是指 DT 中的索引而不是在最后 data.table但这也可以修复。

但是,......我有一种挥之不去的感觉,这样的事情可以在 data.table 的几行中更有效地完成。代码和“轻轻挥手”。谁能指出我正确的方向?

[抱歉发了超长的帖子]


根据以下答案更新。只是为了好玩,我通过 microbenchmark 运行了三个不同的建议。看看这三种方法之间是否会有任何时间差异。 f1()是@Frank 的建议,f2()是@mtoto给出的解决方案,f3是@amatsuo_net 的方法。尝试了长度为 1000 的向量,这是输出

Unit: milliseconds
expr min lq mean median uq max neval cld
f1() 4020.8112 4387.7950 4614.7896 4498.8043 4770.1184 6837.672 100 c
f2() 656.9575 685.7706 727.5191 710.3003 735.2832 1080.423 100 a
f3() 1637.8927 1706.7528 1789.1794 1739.4428 1814.7776 2403.474 100 b

方法上有很大的不同。我需要通过具有 700 万个 ID 的数据集来运行它,这样肯定会产生明显的影响。谢谢大家!

最佳答案

我会尽可能长时间地保留列表栏。

从 sibling 开始,这是一个简单的方法:

sibDT = DT[!is.na(fid) & !is.na(mid), 
CJ(id = id, sid = id)[id != sid]
, by=.(fid, mid)]

# fid mid id sid
# 1: 1 2 3 4
# 2: 1 2 4 3
# 3: 5 6 13 14
# 4: 5 6 14 13

然后将同父异母的 sibling 定义为共享父代但不出现在 sibDT 中:

hsibDT = melt(DT, id = "id")[!is.na(value), 
CJ(id = id, hsid = id)[id != hsid]
, by=.(ptype = variable, pid = value)][!sibDT, on=.(id, hsid = sid)]

# ptype pid id hsid
# 1: fid 5 13 15
# 2: fid 5 14 15
# 3: fid 5 15 13
# 4: fid 5 15 14
# 5: mid 6 12 13
# 6: mid 6 12 14
# 7: mid 6 13 12
# 8: mid 6 14 12

我会在这里停下来,但是要浏览带有列表或字符列的结果...

DT[sibDT[, .(sibs = toString(sid)), by=id], on=.(id), sibs := i.sibs, by=.EACHI ]
DT[hsibDT[, .(hsibs = toString(hsid)), by=id], on=.(id), hsibs := i.hsibs, by=.EACHI ]

# or...

DT[
rbind(sibDT[, .(id, oid = sid)], hsibDT[, .(id, oid = hsid)])[,
.(asibs = toString(oid))
, by=.(id)],
on = .(id),
asibs := i.asibs
, by = .EACHI]

给出

   id fid mid sibs  hsibs      asibs
1: 1 NA 0 NA NA NA
2: 2 9 NA NA NA NA
3: 3 1 2 4 NA 4
4: 4 1 2 3 NA 3
5: 12 7 6 NA 13, 14 13, 14
6: 13 5 6 14 15, 12 14, 15, 12
7: 14 5 6 13 15, 12 13, 15, 12
8: 15 5 8 NA 13, 14 13, 14

将这些列添加到 DT 会适得其反,除非您的分析已完成。我想任何有用的分析都将针对各种表格中包含的非列表列。

关于r - 使用 data.table 的兄弟网络,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44286847/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com