一种方法是将数据框按行转换为单个向量,并根据您要查找的值创建一个逻辑向量,确保将FALSE 转换为NA。然后创建一个与逻辑向量长度相同的重复列名向量、子集并重新转换为矩阵:
> set.seed(1)
> DF = data.frame(first = sample(c(NA,1), 5, T), second = sample(c(NA,1), 5, T),
+ third = sample(c(NA,1), 5, T), fourth = sample(c(NA,1), 5, T),
+ fifth = sample(c(NA,1), 5, T))
> DF
first second third fourth fifth
1 NA 1 NA NA 1
2 NA 1 NA 1 NA
3 1 1 1 1 1
4 1 1 NA NA NA
5 NA NA 1 1 NA
> DFvector = as.vector(t(DF))
> DFvector
[1] NA 1 NA NA 1 NA 1 NA 1 NA 1 1 1 1 1 1 1 NA NA NA NA NA 1 1 NA
# Create a repeated vector of column names
> columnNames = rep(colnames(DF), times = nrow(DF))
> myNames = columnNames[as.logical(DFvector)]
> myNames[is.na(myNames)] = ""
> myNames
[1] "" "second" "" "" "fifth" "" "second" "" "fourth" "" "first"
[12] "second" "third" "fourth" "fifth" "first" "second" "" "" "" "" ""
[23] "third" "fourth" ""
# Convert to matrix, by row
myMatrix = matrix(myNames, ncol = ncol(DF), byrow = T)
# Can group per row, by using assertr package
> library(assertr)
> library(stringr)
> concat = assertr::col_concat(myMatrix[], sep = " ")
> concat
[1] " second fifth" " second fourth " "first second third fourth fifth"
[4] "first second " " third fourth "
> noWS = trimws(concat)
> noWS
[1] "second fifth" "second fourth" "first second third fourth fifth"
[4] "first second" "third fourth"
> noS = gsub(pattern = "\\s+", replacement = " ", x = noWS)
> noS
[1] "second fifth" "second fourth" "first second third fourth fifth"
[4] "first second" "third fourth"
> stringr::str_split(noS, " ", simplify = T)
[,1] [,2] [,3] [,4] [,5]
[1,] "second" "fifth" "" "" ""
[2,] "second" "fourth" "" "" ""
[3,] "first" "second" "third" "fourth" "fifth"
[4,] "first" "second" "" "" ""
[5,] "third" "fourth" "" "" ""
现在您可以使用原始数据框中的相同行来获取每行对应的列名。
我希望有人可以发布data.table/dplyr 替代方案,因为如果要避免使用lapply,这将非常乏味。