【问题标题】:get column name that matches specific row value in dataframe获取与数据框中特定行值匹配的列名
【发布时间】:2016-04-30 20:38:54
【问题描述】:

我正在尝试获取单元格值为 1 的每一行的列名。但是我的尝试没有成功,有人可以提供建议吗?

library(permute)
set.seed(42)
exampledf<- data.frame(allPerms(c(1,2,3,4)))
exampledf<-head(exampledf)

我试过了:

apply(exampledf,2,function(x){
    ll<-x[1]==1
    which(ll==T)
    })

数据集

  X1 X2 X3 X4
1  1  2  4  3
2  1  3  2  4
3  1  3  4  2
4  1  4  2  3
5  1  4  3  2
6  2  1  3  4

我的目标:

X1
X1
X1
X1
X1
X2

【问题讨论】:

  • 试试names(exampledf)[max.col(exampledf == 1)]

标签: r


【解决方案1】:

这是一种方法:

# construct sample data.frame
set.seed(1234)
df <- data.frame(matrix(
                 c(sample(1:4, 4), sample(1:4, 4), 
                   sample(1:4, 4), sample(1:4, 4)), 
                 ncol=4, byrow=T))
# name data.frame
names(df) <- c(paste0("x", 1:4))

# get names of variables
names(df)[apply(df, 1, function(i) which(i == 1))]

@DavidArenburg 建议的一种可能更快的方法(尤其是对于大型数据集)是

names(df)[which(df == 1, arr.ind=T)[, "col"]]

因为它不需要使用apply函数。

注意:我构建了一个不同的 data.frame,因为我没有 permute 包。

【讨论】:

  • 您无需运行apply 即可使用which。只需names(df)[which(df == 1, arr.ind = TRUE)[, "col"]] 即可。
  • which ... [, "col"] 版本将按列的顺序返回结果。对于给出的示例,这没有问题,但如果第一行是4, 3, 2, 1,则结果将返回为X1, X1, X1, X1, X2, X4。需要一个中间步骤来按"row" 列对which 的输出进行排序。
【解决方案2】:

我希望我能正确回答您的问题(最后匹配的列不应该是 X2 而不是 X3?)。有点老派,但如果我猜对了,这应该可以。

library(permute)
set.seed(42)
exampledf <- data.frame(allPerms(c(1,2,3,4)))
exampledf <- head(exampledf)

matched_cols = c()
for(i in 1:nrow(exampledf)){
    row <- edf[i, ] == 1
    matched_col <- colnames(exampledf)[row == T] 
    matched_cols = c(matched_cols, matched_col)  
}
matched_cols

【讨论】:

  • 避免在 R 或任何其他语言中增长对象通常是个好主意。当您知道要填充的对象的大小(这里等于数据框的行数)时,最好预先分配一个该大小的向量来存储数据。在exampledf &lt;- head... 下方,您应该初始化您的matched_cols 向量:matched_cols &lt;- integer(nrow(exampledf))。然后,您可以使用matched_cols[i] &lt;- ... 填写matched_cols 并为R 省去每次迭代都必须重复复制matched_cols 的工作。
【解决方案3】:

另一种简单的方法:

library(permute)
set.seed(42)
exampledf<- data.frame(allPerms(c(1,2,3,4)))

for(i in 1:nrow(exampledf)){
    for (j in 1:length(exampledf[i,])){
        if(exampledf[i,j]==1){
           print(names(exampledf)[j])
        }
    }
}

示例输出为:

“X1”

“X1”

“X1”

“X1”

“X1”

“X2”

“X2”

“X3”

【讨论】:

    【解决方案4】:

    如果数据框在这些列中有多个值 1,则可以使用它来实现,尽管它也是一对一的值

    exampledf$results<-c() # Adding one empty column called results here 
    for(i in (1:nrow(exampledf))){
        exampledf$results[i] <- paste((colnames(exampledf)[which(exampledf[i,1:(ncol(exampledf)-1)] ==  1)]),collapse = ",")
    }
    

    希望对本帖有所帮助

    【讨论】:

    • 抱歉打错了,我希望打印所有大于 1 的值
    猜你喜欢
    • 2019-01-29
    • 2021-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-22
    • 1970-01-01
    • 2017-10-18
    相关资源
    最近更新 更多