不具有NULL值的列名称的必需顺序

时间:2017-04-18 17:45:46

标签: r data.table

我的数据有点典型,我需要找出符合某种模式的字段/列顺序。

对于Instance,一个字段(比如sub3)有值直到某些行,然后是NULL值,然后另一个字段将继续一些值(如Sub1),然后跟随空值。

在某些情况下,我可能有多个字段的值为两行(如Sub2和Sub4)。

在下面的例子中,解决方案是字段名称的向量,它遵循模式c(Sub3,Sub1,c(Sub2,Sub4),Sub5)

这是可重现的数据格式和数据快照。

structure(list(RollNo = 1:10, Sub1 = c(NA, NA, NA, NA, 3L, 2L, 
    NA, NA, NA, NA), Sub2 = c(NA, NA, NA, NA, NA, NA, "A", "B", NA, 
    NA), Sub3 = c(4L, 3L, 5L, 6L, NA, NA, NA, NA, NA, NA), Sub4 = c(NA, 
    NA, NA, NA, NA, NA, 2L, 5L, NA, NA), Sub5 = c(NA, NA, NA, NA, 
    NA, NA, NA, NA, 7L, NA)), .Names = c("RollNo", "Sub1", "Sub2", 
    "Sub3", "Sub4", "Sub5"), row.names = c(NA, -10L), class = c("data.table", 
    "data.frame"), .internal.selfref = <pointer: 0x0000000000200788>)

SnapShot of the data

2 个答案:

答案 0 :(得分:2)

听起来你正在按照第一个非NA数据的顺序进行排序。如果df是您的数据:

sapply(df, function(x) min(Inf, head(which(!is.na(x)),n=1)))
# RollNo   Sub1   Sub2   Sub3   Sub4   Sub5 
#      1      5      7      1      7      9 

为每列提供第一个非NA行。这应该是一种自然的类型,这意味着关系保留了关系之间的原始顺序。

有几种方法可以使用它,例如:

order(sapply(df, function(x) min(Inf, head(which(!is.na(x)),n=1))))
# [1] 1 4 2 3 5 6
df[,order(sapply(df, function(x) min(Inf, head(which(!is.na(x)),n=1))))]
#    RollNo Sub3 Sub1 Sub2 Sub4 Sub5
# 1       1    4   NA <NA>   NA   NA
# 2       2    3   NA <NA>   NA   NA
# 3       3    5   NA <NA>   NA   NA
# 4       4    6   NA <NA>   NA   NA
# 5       5   NA    3 <NA>   NA   NA
# 6       6   NA    2 <NA>   NA   NA
# 7       7   NA   NA    A    2   NA
# 8       8   NA   NA    B    5   NA
# 9       9   NA   NA <NA>   NA    7
# 10     10   NA   NA <NA>   NA   NA

我从列名称推断RollNo应该始终是第一个,所以:

df[,c(1, 1 + order(sapply(df[-1], function(x) min(Inf, head(which(!is.na(x)),n=1)))))]

答案 1 :(得分:1)

使用:

DT[, nms := paste0(names(.SD)[!is.na(.SD)], collapse = ','), 1:nrow(DT), .SDcols = 2:6]

会得到你:

> DT
    RollNo Sub1 Sub2 Sub3 Sub4 Sub5       nms
 1:      1   NA   NA    4   NA   NA      Sub3
 2:      2   NA   NA    3   NA   NA      Sub3
 3:      3   NA   NA    5   NA   NA      Sub3
 4:      4   NA   NA    6   NA   NA      Sub3
 5:      5    3   NA   NA   NA   NA      Sub1
 6:      6    2   NA   NA   NA   NA      Sub1
 7:      7   NA    A   NA    2   NA Sub2,Sub4
 8:      8   NA    B   NA    5   NA Sub2,Sub4
 9:      9   NA   NA   NA   NA    7      Sub5
10:     10   NA   NA   NA   NA   NA          

如果您只想要指定的矢量:

unique(DT[, paste0(names(.SD)[!is.na(.SD)], collapse = ','), 1:nrow(DT), .SDcols = 2:6][V1!='']$V1)

返回:

[1] "Sub3"      "Sub1"      "Sub2,Sub4" "Sub5"

正如@Frank在评论中所说,你也可以使用:

melt(DT, id=1, na.rm = TRUE)[, toString(unique(variable)), by = RollNo][order(RollNo)]