有条件地为所选列中的所有值更新一些列(data.table,r)

时间:2016-01-14 13:39:46

标签: r data.table

我有900,000 x 500类型的数据集,但下面显示了适合该问题的玩具数据集。

library(data.table)
df1 <- data.table(x = c(1,2,4,0), y = c(0,0,10,15), z = c(1,1,1,0))

我想做以下事情:

  1. 对于y和z列
  2. 选择行= 0
  3. 的值
  4. 用max + 1替换它们,其中max是在整个列上计算的
  5. 我是data.table的新手。在stackoverflow上查看问题的示例,我找不到类似的问题,除了这个: How to replace NA values in a table *for selected columns*? data.frame, data.table

    我自己的尝试如下,但这不起作用:

    for (col in c("x", "y")) df1[(get(col)) == 0, (col) := max(col) + 1)
    

    显然,我还没有习惯data.table,所以我现在正撞在墙上......

    如果除了dplyr之外还有人可以提供data.table解决方案,我会很感激。

3 个答案:

答案 0 :(得分:6)

我们可以使用set并将值为0的行与该列的max +1分配。

 for(j in c("y", "z")){
    set(df1, i= which(!df1[[j]]), j=j, value= max(df1[[j]])+1)
 }

df1
#   x  y z
#1: 1 16 1
#2: 2 16 1
#3: 4 10 1
#4: 0 15 2

注意:set方法非常有效,因为避免了[.data.table的开销

或者效率较低的方法是在.SDcols中指定感兴趣的列,循环遍历列(lapply(..),replace基于逻辑索引的值,并分配(:=)输出回到列。

df1[, c('y', 'z') := lapply(.SD, function(x) 
         replace(x, !x, max(x)+1)), .SDcols= y:z]

答案 1 :(得分:2)

dplyr版本非常简单(我认为)

> library(dplyr)
# indented for clarity
> mutate(df1, 
    y= ifelse(y>0, y, max(y)+1), 
    z= ifelse(z>0, z, max(z)+1))

  x  y z
1 1 16 1
2 2 16 1
3 4 10 1
4 0 15 2

修改 正如David Arenburg在评论中指出的那样,这对于玩具示例是有帮助的,但对于提及500列的数据则没有。他提出类似的建议:

df1 %>% mutate_each(funs(ifelse(. > 0, ., max(.) + 1)), -1)

其中-1指定除第一列以外的所有列

答案 2 :(得分:1)

作为替代方案,ifelse(test, yes, no)可能有用

沿线

library(data.table)
dt <- data.table(x = c(1,2,4,0), y = c(0,0,10,15), z = c(1,1,1,0))

print(dt)

dt[, y := ifelse(!y, max(y) + 1, y)]

print(dt)