Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 如何执行一个;“串行连接”;在data.table中?_R_Data.table - Fatal编程技术网

R 如何执行一个;“串行连接”;在data.table中?

R 如何执行一个;“串行连接”;在data.table中?,r,data.table,R,Data.table,我有两个数据表:一个实验数据表x和一个类别查找表dict library(data.table) set.seed(123) x = data.table(samp=c(1,1,2,3,3,3,4,5,5,5,6,7,7,7,8,9,9,10,10), y=rnorm(19)) x samp y #1: 1 -0.56047565 #2: 1 -0.23017749 #3: 2 1.55870831 #4: 3 0.07050839 #5: 3 0.

我有两个数据表:一个实验数据表
x
和一个类别查找表
dict

library(data.table)
set.seed(123)

x = data.table(samp=c(1,1,2,3,3,3,4,5,5,5,6,7,7,7,8,9,9,10,10), y=rnorm(19))
x

     samp    y
 #1:  1 -0.56047565
 #2:  1 -0.23017749
 #3:  2  1.55870831
 #4:  3  0.07050839
 #5:  3  0.12928774
 #6:  3  1.71506499
 #7:  4  0.46091621
 #8:  5 -1.26506123
 #9:  5 -0.68685285
#10:  5 -0.44566197
#11:  6  1.22408180
#12:  7  0.35981383
#13:  7  0.40077145
#14:  7  0.11068272
#15:  8 -0.55584113
#16:  9  1.78691314
#17:  9  0.49785048
#18: 10 -1.96661716
#19: 10  0.70135590

dict = data.table(samp=c(1:5, 4:8, 7:10), cat=c(rep(1,length(1:5)), rep(2,length(4:8)), rep(3,length(7:10))))

dict
#     samp cat
# 1:  1   1
# 2:  2   1
# 3:  3   1
# 4:  4   1
# 5:  5   1
# 6:  4   2
# 7:  5   2
# 8:  6   2
# 9:  7   2
# 10:  8   2
# 11:  7   3
# 12:  8   3
# 13:  9   3
# 14: 10   3
对于每个
samp
,我需要首先计算与之关联的所有
y
的乘积。然后,我需要根据
dict$cat
中指定的每个样本类别计算这些产品的总和。请注意,每个
samp
映射到多个
dict$cat

一种方法是立即合并
x
dict
,允许行复制(
allow.cartesian=T
):

然而,我不知道是否可以避免这一加入步骤。这有几个原因-例如,如果
x
很大,复制将使用额外的内存(对吗?)。此外,这些具有重复行的汇总表非常混乱,使得分析更容易出错

因此,我考虑在每个
dict$cat
中使用示例在
x
中进行二进制搜索。我知道如何对单个类别执行此操作,因此对所有类别执行此操作的丑陋方式是使用循环:

setkey(x, samp)
setkey(dict,samp)

pool = vector("list") 
for(n in unique(dict$cat)){
    thisCat = x[J(dict[cat==n])]
    setkey(thisCat, samp)
    step1 = thisCat[, list(prodY=prod(y)[1], cat=cat[1]), by="samp"]
    pool[[n]] = step1[, sum(prodY), by="cat"]        
}
resMet2 = rbindlist(pool)

当然,这种循环是要避免的。因此,我想知道是否有任何方法可以以某种方式获取
数据.table
来迭代
J()
中的键值?

您不妨先将
x
折叠到
samp
级别

xprod = x[, .(py = prod(y)), by=samp]
合并

res2 <- xprod[dict, on = "samp"][, sum(py), by=cat]

identical(res2, resMet2) # test passed

重新标记样本ID非常简单,因此这是真实的。

IIUC,我将您的问题表述如下:对于每个
dict$cat
,我希望得到对应于该
cat
的每个
样本的
prod(y)
,然后将它们全部加起来

现在让我们一步一步地构造这个:

  • 对于每个
    dict$cat
    -听起来您需要按
    cat
    分组:

    dict[, ,by=cat]
    
    剩下的就是正确地加注
    j

  • 对于该组的每个样本,您需要从
    x
    获取
    prod(y)

    从与该组的
    samp
    对应的
    x
    中提取那些行(使用
    .SD
    ,它代表数据子集),并计算它们上的
    prod(y)
    ,按
    samp
    分组。太好了

  • 我们仍然需要对它们进行汇总

    sum(x[samp %in% .SD$samp, prod(y), by=samp]$V1)
    
  • 我们得到了完整的
    j
    表达式。让我们将其全部插入:

    dict[, sum(x[samp %in% .SD$samp, prod(y), by=samp]$V1), by=cat]
    #    cat         V1
    # 1:   1  1.7770272
    # 2:   2  0.7578771
    # 3:   3 -1.0295633
    
  • 希望这有帮助


    注1:这里有一些多余的
    prod(y)
    计算,但好处是我们没有实现太多中间数据。所以它的内存效率很高。如果您有太多的组,这可能会变慢。。您可能需要在另一个变量中计算
    prod(y)
    ,如下所示:

    x_p = x[, .(p = prod(y)), by=samp]
    
    这样,我们可以简化
    j
    ,如下所示:

    dict[, x_p[samp %in% .SD$samp, sum(p)], by=cat]
    

    注意2:在%
    表达式中的
    %在
    x的
    列上第一次运行时创建一个自动索引,从那时起使用基于二进制搜索的子集。因此,不必担心矢量扫描带来的性能问题。

    我不知道%in%是以这种方式优化的。请参阅。在某个时候,我会把它包装成一个小插曲…
    foverlaps()
    在这里可能会有点过头。就像更简单的解决方案。
    dict[, sum(x[samp %in% .SD$samp, prod(y), by=samp]$V1), by=cat]
    #    cat         V1
    # 1:   1  1.7770272
    # 2:   2  0.7578771
    # 3:   3 -1.0295633
    
    x_p = x[, .(p = prod(y)), by=samp]
    
    dict[, x_p[samp %in% .SD$samp, sum(p)], by=cat]