【问题标题】:Index of an R data.table column with the smallest element具有最小元素的 R data.table 列的索引
【发布时间】:2016-10-07 01:33:18
【问题描述】:

我有一个缺少值的 data.table,其中某些行仅包含 NA。 data.table 实际上是较大 data.table 的列的子集,所以我想避免删除所有 NA 行。我想找到一种优雅的方法来找到每行中具有最小元素的列的索引,并将结果数组作为新列添加到data.table。对于所有 NA 行,我想要一个 NA 结果。这是一种不优雅的方法:

> dt <- data.table(x=c(1,NA,3),y=c(2,NA,NA),z=c(3,NA,1))
> dt
    x  y  z
1:  1  2  3
2: NA NA NA
3:  3 NA  1
> w <- apply(dt,1,which.min)
> w
[[1]]
x 
1 

[[2]]
integer(0)

[[3]]
z 
3 

> v <- unlist(lapply(w,function(z) ifelse(length(z)==0, NA, z[1])))
> v
[1]  1 NA  3
> dt$idx <- v
> dt
    x  y  z idx
1:  1  2  3   1
2: NA NA NA  NA
3:  3 NA  1   3

如您所见,不优雅的主要原因是apply 创建了一个列表而不是一个数组。发生这种情况是因为每行的结果长度不同。另外,我正在调用 base-R 函数 which.minapplyunlistlapply有没有一种简洁的data.table 方式来获得想要的结果?

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    使用 .SD

    d[, idx := apply(.SD, 1, which.min), .SDcols = c('x', 'y', 'z')]
    

    但是所有 NA 行都是空白的;实际上,由于第 2 行都是 NA,which.min 将返回 integer(0),因此 apply 的结果长度不等,而 d$idx 是一个列表(其中的第二个元素是零长度向量);

       > d
        x  y  z idx
    1:  1  2  3   1
    2: NA NA NA    
    3:  3 NA  1   3
    
    > d$idx
    [[1]]
    x 
    1 
    
    [[2]]
    integer(0)
    
    [[3]]
    z 
    3 
    

    因此在这些情况下处理零长度向量并将返回设置为 NA;

    d[, idx := apply(.SD, 1, function(x) which.min(x)[1] ), .SDcols = c('x', 'y', 'z')]
    > d$idx
    [1]  1 NA  3
    

    【讨论】:

    • 我认为第一种情况下的空白代表一个空列表。看起来整个列都属于列表类。如果有人想写.csv,这可能是个问题。第二种选择也是处理这种烦恼。不过,是否有更短的方法来编写第二个选项?
    • @user3605620。是的,第一种方法是添加一列列表。我已经编辑了答案。
    • 在外部编写一个自定义的which.min 函数会使这一行更短。我想不出别的办法。 :(
    • 我认为最好的方法是使用 max.colrowSums 与 akrun 的 NA^x 技巧:stackoverflow.com/a/39275278 当然,这仍然不是像 OP 那样的“data.table 方式”想要,但他们可能应该在这里使用矩阵或重塑他们的数据。更多示例:stackoverflow.com/search?q=user%3A3732271+NA+rowsums+max.col
    • @user3605620 - data.table 效率不高只是因为。如果您使用 apply 并循环遍历每一行,您可能会将大部分效率抛到窗外。
    猜你喜欢
    • 2011-02-22
    • 1970-01-01
    • 2015-07-12
    • 1970-01-01
    • 2012-03-30
    • 1970-01-01
    • 2017-08-26
    • 1970-01-01
    • 2014-09-22
    相关资源
    最近更新 更多