R:在data.table中应用行方式替换,以特定列中的值为条件

时间:2017-09-20 14:47:47

标签: r data.table row apply

我知道还有更多这样的问题。但是,我无法完成它。 我有一个非常大的data.table,大约有800.000行。每行包含一些特定数据,然后是一些需求数据2年(从第12列开始),最后一列是一个数字。此数字确定应替换的需求列数。

一行示例:

ITEM COUNTRY Q1 Q2 Q3 Q4 ---- Q24 NUMBER 
1          1  0  0  0  0 ----   2      2

例如,如果这是一个名为x的向量,我会这样做:

x[2:(2+x$NUMBER-1)] <- NA 

现在我想对所有行执行此操作。 for循环太慢了。所以我在考虑申请。

fun_NA <- function(x){ #x is then a row of the data.table
#still use that with x[,] as x is still a data.table and not a vector 

    if(x[,60]>0){
        x[,12:(12+as.numeric(x[,60])-1)] <- NA  
    }
}

dt = apply(dt, 1, fun_NA)

其中dt是我的data.table,有60列。第一个需求值从第12列开始。它不起作用..现在它在x [,60]中给出了错误&#34;错误:维数不正确&#34;,但我也尝试了其他方法并收到其他错误。

我想要这样做的原因: 该数字表示该项目能够销售的月份(在我的数据集的第一个月之后),因此在之前的几个月中,需求不是0,但是根本不存在。我需要它是NA,因为0将在以后导致错误的计算。

编辑: 删除了逗号,这是新代码,

fun_NA <- function(x){ #x is then a row of the data.table

        if(x[60]>0){
            x[12:(12+as.numeric(x[60])-1)] <- NA    
        }
    }

dt = apply(dt, 1, fun_NA)

但是,这会返回一个包含所有NULL和NA元素的大型列表。

编辑:数据表的头部如下:( dput)

structure(list(ITEM = c(1, 1, 2, 2, 2, 2), COUNTRY = c(1, 2, 
3, 4, 5, 2), DATE = c("2015-02-02", "2015-02-02", "2014-09-27", 
"2014-09-27", "2014-09-27", "2014-09-27"), q_1 = c(0, 0, 2, 0, 
0, 133), q_2 = c(0, 0, 24, 0, 9, 119), q_3 = c(0, 0, 15, 0, 13, 
121), q_4 = c(0, 0, 7, 0, 2, 51), q_5 = c(0, 0, 12, 0, 6, 59), 
    q_6 = c(0, 0, 3, 0, 0, 36), q_7 = c(0, 0, 6, 0, 6, 41), q_8 = c(0, 
    0, 19, 0, 4, 42), q_9 = c(0, 0, 3, 0, 5, 48), q_10 = c(0, 
    0, 5, 0, 11, 49), q_11 = c(0, 0, 6, 0, 1, 42), q_12 = c(0, 
    0, 0, 0, 8, 70), q_13 = c(0, 0, 1, 0, 19, 81), q_14 = c(0, 
    0, 5, 0, 98, 86), q_15 = c(0, 0, 12, 0, 10, 152), q_16 = c(0, 
    0, 7, 0, 8, 95), q_17 = c(0, 0, 30, 0, 5, 62), q_18 = c(0, 
    0, 6, 0, 10, 47), q_19 = c(0, 0, 7, 0, 1, 35), q_20 = c(2, 
    0, 7, 0, 0, 47), q_21 = c(0, 2, 16, 5, 4, 70), q_22 = c(0, 
    0, 7, 0, 7, 46), q_23 = c(0, 0, 8, 0, 79, 20), q_24 = c(0, 
    0, 5, 0, 26, 45), NUMBER = c(13, 13, 8, 8, 8, 8)), .Names = c("ITEM", 
"COUNTRY", "DATE", "q_1", "q_2", "q_3", "q_4", "q_5", "q_6", 
"q_7", "q_8", "q_9", "q_10", "q_11", "q_12", "q_13", "q_14", 
"q_15", "q_16", "q_17", "q_18", "q_19", "q_20", "q_21", "q_22", 
"q_23", "q_24", "NUMBER"), class = c("data.table", "data.frame"
), row.names = c(NA, -6L), .internal.selfref = <pointer: 0x0000000004490788>)

2 个答案:

答案 0 :(得分:1)

通常,按列工作更有效。

lapply(1:24, function(i) dt[i <= NUMBER, (paste0("q_", i)) := NA])
   ITEM COUNTRY       DATE q_1 q_2 q_3 q_4 q_5 q_6 q_7 q_8 q_9 q_10 q_11 q_12 q_13 q_14 q_15 q_16 q_17 q_18 q_19 q_20
1:    1       1 2015-02-02  NA  NA  NA  NA  NA  NA  NA  NA  NA   NA   NA   NA   NA    0    0    0    0    0    0    2
2:    1       2 2015-02-02  NA  NA  NA  NA  NA  NA  NA  NA  NA   NA   NA   NA   NA    0    0    0    0    0    0    0
3:    2       3 2014-09-27  NA  NA  NA  NA  NA  NA  NA  NA   3    5    6    0    1    5   12    7   30    6    7    7
4:    2       4 2014-09-27  NA  NA  NA  NA  NA  NA  NA  NA   0    0    0    0    0    0    0    0    0    0    0    0
5:    2       5 2014-09-27  NA  NA  NA  NA  NA  NA  NA  NA   5   11    1    8   19   98   10    8    5   10    1    0
6:    2       2 2014-09-27  NA  NA  NA  NA  NA  NA  NA  NA  48   49   42   70   81   86  152   95   62   47   35   47
   q_21 q_22 q_23 q_24 NUMBER
1:    0    0    0    0     13
2:    2    0    0    0     13
3:   16    7    8    5      8
4:    5    0    0    0      8
5:    4    7   79   26      8
6:   70   46   20   45      8

解释

我们遍历所有24列。对于每一行,测试当前列中的值是否需要根据其列号替换为NA。这些值会在适当的位置更新,从而节省时间和内存。

我已经使用100万行的样本数据集测试了该解决方案,花费的时间不到0.2秒。

答案 1 :(得分:0)

由于你对函数的输入是一个向量,你应该删除所有的逗号,因为它只有一个维度。

fun_NA <- function(x){ #x is then a row of the data.table
#still use that with x[,] as x is still a data.table and not a vector 

    if(x[60]>0){
        x[12:(12+as.numeric(x[60])-1)] <- NA  
    }
}

dt = apply(dt, 1, fun_NA)