首页 > 解决方案 > 在 data.table 中按行提取和折叠非缺失元素

问题描述

我想连续提取所有唯一的非缺失元素,然后使用&&&&. 这里有一个小例子:

#Load needed libraries:
library(data.table)

#Generate the data:
set.seed(1)
n_rows<-10

#Define function to apply to rows:
function_non_missing<-function(x){
  x<-x[!is.na(x)]
  x<-x[x!="NA"]
  x<-unique(x[order(x)])
  paste(x,collapse="&&&&")
}

data<-data.table(
  a=sample(c(1,2,NA,NA),n_rows,replace=TRUE),
  b=sample(c(1,2,NA,NA),n_rows,replace=TRUE),
  c=sample(c(1,2,NA,NA),n_rows,replace=TRUE)
)

> data
     a  b  c
 1:  1 NA  1
 2: NA NA NA
 3: NA  1  1
 4:  1  1  1
 5:  2  1  1
 6:  1  2  1
 7: NA  2  2
 8: NA  2  1
 9:  2  2  1
10:  2 NA  2

#Obtain results
data[,paste(.SD),by=1:nrow(data)][,function_non_missing(V1),by=nrow]

    nrow     V1
 1:    1      1
 2:    2       
 3:    3      1
 4:    4      1
 5:    5 1&&&&2
 6:    6 1&&&&2
 7:    7      2
 8:    8 1&&&&2
 9:    9 1&&&&2
10:   10      2

上面的代码看起来很复杂,我相信可能会有更好的解决方案。

标签: rdata.table

解决方案


使用melt()/ dcast()

data[, row := .I
     ][, melt(.SD, id.vars = "row")
        ][order(row, value), paste0(unique(value[!is.na(value)]), collapse = "&&&"), by = row]

    row    V1
 1:   1     1
 2:   2      
 3:   3     1
 4:   4     1
 5:   5 1&&&2
 6:   6 1&&&2
 7:   7     2
 8:   8 1&&&2
 9:   9 1&&&2
10:  10     2

或者使用您的原始功能:

data[, function_non_missing(unlist(.SD)), by = 1:nrow(data)]

    nrow     V1
 1:    1      1
 2:    2       
 3:    3      2
 4:    4 1&&&&2
 5:    5 1&&&&2
 6:    6 1&&&&2
 7:    7      1
 8:    8      2
 9:    9 1&&&&2
10:   10 1&&&&2

推荐阅读