【问题标题】:R: Apply row-wise replacement in data.table conditional on value in specific columnR:根据特定列中的值在 data.table 中应用逐行替换
【发布时间】:2017-09-20 14:47:46
【问题描述】:

我知道还有更多这样的问题。但是,我无法完成它。 我有一个非常大的 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] 中的错误:维度数不正确”,但我也尝试了其他方法并收到其他错误。

我想这样做的原因: 该数字表示该项目能够销售的月份(我的数据集的第一个月之后),因此在之前的几个月中,需求不是 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>)

【问题讨论】:

标签: r data.table row apply


【解决方案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 秒。

【讨论】:

  • 谢谢!!我会测试它,但它是有道理的,看起来很不错。
【解决方案2】:

由于您对函数的输入是一个向量,因此您应该去掉所有的逗号,因为它只有一维。

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)

【讨论】:

  • 是的,我是第一个这样做的,但这不起作用,因为我以第一行为例进行了尝试。我用 x=dt[1,] 尝试过,然后 class(x) 产生“data.table”“data.frame”,我必须通过 x[,2]调用 x 的第二个元素>
  • 另见我在函数中的评论。
  • 好吧,我错了。在应用中,它显然需要不带逗号。现在需要几秒钟才能终止,没有任何错误。但是,我得到一个只有 NULL 的非常大的列表,所以它不能正常工作......
  • 嗯,我认为问题可能出在函数中......你能 dput(head(x)) 让我测试一下吗?
  • 我添加了我的 data.table 的简化版本的头部(因此较小的列和函数 fun_NA 应该从第 4 列开始,现在替换,而不是 12,基于最后一列中的数字.
猜你喜欢
  • 2022-07-14
  • 2022-12-31
  • 2016-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-24
相关资源
最近更新 更多