R语言 对data.table中的多个列应用多个不同的条件

f2uvfpb9  于 2023-05-20  发布在  其他
关注(0)|答案(1)|浏览(85)

给定一个data.table

dt <- data.table(
        year = c(2020, 2021, 2022), 
        b    = c(10, 20, 30), 
        c    = c(100, 200, 300)
      )

我想根据不同的条件覆盖多个列。下面我使用了一个for循环来获得我想要的基本功能。

cols_to_update <- c("b", "c") 
conds <- c(2020, 2022)

for ( i in seq_along(cols_to_update)) { 
    dt[year == conds[i], (cols_to_update[i]) := NaN] 
})

print(dt)

我需要的最终输出应该是

year  b   c
1: 2020 NaN 100
2: 2021  20 200
3: 2022  30 NaN

我是新来的R和数据。表,我试图填补我的知识。为此,我怀疑在data.table中有一种更快、更简洁的方法来实现这一点,可能是使用lapply和.SD cols,但我没有找到这种方法。棘手的部分是将每个不同的条件应用于相应的列。
在这种情况下,条件总是基于同一列(即年份)。
这段代码运行得很好,尽管我担心for循环相对于data.table的效率可能有点慢(如果是这样的话,请随时告诉我这是一个愚蠢的问题)。

bf1o4zei

bf1o4zei1#

dt[, c(cols_to_update) :=
  Map(
    function(x, yr) replace(x, year == yr, NaN),
    .SD, conds),
  .SDcols = cols_to_update ]
dt
#     year     b     c
#    <num> <num> <num>
# 1:  2020   NaN   100
# 2:  2021    20   200
# 3:  2022    30   NaN

如果您曾经在data.table类管道中看到过lapply(.SD, fun),那么Map(fun, .SD)非常类似,但它允许将其他东西“压缩”在一起。在本例中,Map(fun, .SD[,cols_to_update], conds)展开为(有效地)

fun(dt$b, conds[1])
fun(dt$c, conds[2])

然后存储回cols_to_update
但说实话,这确实降低了data.table的效率。如果你想尽可能快,这可能会胜出(使用合理大小的数据):

for (i in seq_along(cols_to_update)) {
  set(dt, i = which(dt$year == conds[i]), j = cols_to_update[i], value = NaN)
}

相关问题