【问题标题】:R loop using data.tableR循环使用data.table
【发布时间】:2021-06-25 23:13:06
【问题描述】:

我有一个大约 300 万行的数据集。我创建了一个如下所示的小示例:

ex <- data.table(eoc = c(1,1,1,1,1,2,2,2,3,3), proc1 = c(63035,63020,92344,63035,27567,63020,1234,55678,61112,1236), trigger_cpt = c(63020,63020,63020,63020,63020,63020,63020,63020,61112,61112))

我有另一个 42 行的数据集,但生成了一个较小的示例:

add_on <- data.table(primary = c(63020,61112), secondary=c(63035,63445))

我需要重新标记“trigger_cpt”列上的某些行(按 eoc 分组)如果 trigger_cpt 值恰好是数据集主列中的值之一并且 如果 proc1 值是 add_on 数据集中的次要值。如果符合条件,则trigger_cpt应重新标记为二级代码。

我最初是手动输入所有内容, ex[,trigger_new := if(any(trigger_cpt == '63020' &amp; proc1 == '63035')) 63035 else trigger_cpt, eoc]

然后决定做一个for循环

for(i in 1:nrow(add_on)){
  ex[,trigger_new2 := if(any(trigger_cpt == add_on[i,1] & proc1 == add_on[i,2])) add_on[i,2] else trigger_cpt, eoc]
}

但是,现在我正在我的 300 万行数据集上尝试此代码,运行它需要很长时间。我不确定是否有更好的方法,或者是否可以对我当前的代码进行任何修改?

任何帮助将不胜感激!

预期输出:

ex_final <- data.table(eoc = c(1,1,1,1,1,2,2,2,3,3), proc1 = c(63035,63020,92344,63035,27567,63020,1234,55678,61112,1236), trigger_cpt = c(63035,63035,63035,63035,63035,63020,63020,63020,61112,61112))

【问题讨论】:

  • 如果 add_on 中的 'eoc' 有不同的值。那么您可能需要使用这些值在“add_on”中创建一个“eoc”列,然后通过“eoc”与其他列进行连接

标签: r for-loop data.table tidyverse


【解决方案1】:

这是一种生成 data.table 的方法,如果在分组集中找到匹配项,则将所有 trigger_cpt 设置为辅助值:


ex2 <- add_on[ex, , on=.(primary=trigger_cpt)][ , trigger_new := fifelse( secondary %in% proc1, secondary, NA_real_ ), by=eoc ]
ex.final  <- ex2[ , trigger_cpt := fcoalesce( trigger_new, primary ) ][, .(eoc,proc1,trigger_cpt) ]

输出:


> ex.final
    eoc proc1 trigger_cpt
 1:   1 63035       63035
 2:   1 63020       63035
 3:   1 92344       63035
 4:   1 63035       63035
 5:   1 27567       63035
 6:   2 63020       63020
 7:   2  1234       63020
 8:   2 55678       63020
 9:   3 61112       61112
10:   3  1236       61112

此外,如果可行(这是有代价的),我会考虑使用setkey,除非它弊大于利。 (初始处理可能使其不值得)。它加快了下游操作,并且可能使 join 代码更加简洁。 data.table 代码可能已经够难了。因此:


setkey(ex, trigger_cpt )
setkey(add_on, primary )

## can now do this:
add_on[ex]

## instead of this:
add_on[ex, , on=.(primary=trigger_cpt)]

## .. in the code above.

...此外...

如果您正在修改上述步骤,您会注意到add_on[ex](这是在 data.table 中执行 left join 的有点倒退的方式),留下了 add_on 的键 列名称,而不是 ex 的列名称。这并不重要,只要您知道并最终适当地重命名列,但是加入数据的另一种方法可能是:


ex2 <- merge( ex, add_on, by.x="trigger_cpt", by.y="primary" )
## and then work your way till the end with what this gives you

【讨论】:

    【解决方案2】:

    基于预期输出

    ex[, trigger_new := first(proc1), eoc]
    
    
    
    
    ex
        eoc proc1 trigger_cpt trigger_new
     1:   1 63035       63020       63035
     2:   1 63020       63020       63035
     3:   1 92344       63020       63035
     4:   1 63035       63020       63035
     5:   1 27567       63020       63035
     6:   2 63020       63020       63020
     7:   2  1234       63020       63020
     8:   2 55678       63020       63020
     9:   3 61112       61112       61112
    10:   3  1236       61112       61112
    

    【讨论】:

    • 有什么办法可以按列 eoc 分组吗?这样对于 eoc 1,每个 trigger_new 都是 63035
    • @vizidea 你能显示预期的输出吗?根据您的代码,似乎不需要按 eoc 分组 1.您按每一行循环,那么分组列无关
    • 我添加了想要的输出
    猜你喜欢
    • 1970-01-01
    • 2016-02-15
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多