如何检索数据框中的列名

4
我将尝试提取数据帧中的列名,基于单元格中的值。我的数据是一系列几百个类别,单元格中有简单的二进制0或1,表示我想在新数据框中使用哪个列名。
为了说明我的观点:
year cat1 cat2 cat3 ... catN
2000  0    0    1        0
2001  1    0    0        0
2002  0    0    0        1
....
2018  0    1    0        0

我想要得到一个类似于以下结构的数据框:

year category 
2000  cat3
2001  cat1  
2002  catN  
....
2018  cat2  

我的代码:

newdf <- as.data.frame(colnames(mydf)[which(mydf == "1", arr.ind = TRUE)[2]])

但是很遗憾,这只返回一个类别名称!如有帮助将不胜感激!

仔细研究dplyrtidyr包,或者更复杂的data.table。它们被设计来做这件事情。 - Andre Elrico
6个回答

4

基本的R解决方案:

使用sapply查找这些内容并获取名称。

out <- data.frame(year = df1$year, category = names(sapply(df1[, -1], function(x) which(x == 1))))

out
 year category
1 2000     cat1
2 2001     cat2
3 2002     cat3
4 2018     catN

数据:

df1 <- structure(list(year = c(2000L, 2001L, 2002L, 2018L), cat1 = c(0L, 
1L, 0L, 0L), cat2 = c(0L, 0L, 0L, 1L), cat3 = c(1L, 0L, 0L, 0L
), catN = c(0L, 0L, 1L, 0L)), class = "data.frame", row.names = c(NA, 
-4L))

忍者。运行得很好。 - Dan
将上述内容应用于我的数据时,我使用了as.data.frame来强制将我的数据转换为数据框,但是更改后的代码返回:缺少参数“x”,没有默认值...我是否对某些事情感到困惑? - Dan
我已经复制了代码,将df1替换为我的数据框名称。数据参数中可能缺少什么?(为了澄清sapply(df1 [,-1]等中的数据参数是df1吗?) - Dan
它输出所有列名或“类别”。 - Dan
完整的sapply返回带有相应0或1的类别。names(sapply...)返回类似于以下内容的东西:[1] "cat1" "cat2" [3] "cat3" "cat4" - Dan
让我们在聊天中继续这个讨论 - phiver

3
一个可能的解决方案是这样的:
library(tidyverse)

df = data.frame(year = 2000:2002,
                cat1 = c(0,0,1),
                cat2 = c(1,0,0),
                cat3 = c(0,1,0))

df %>%
  gather(category, value, -year) %>%  # reshape data
  filter(value == 1) %>%              # keep rows with 1s
  select(-value) %>%                  # remove that column
  arrange(year)                       # order that column (if needed)

#   year category
# 1 2000     cat2
# 2 2001     cat3
# 3 2002     cat1

3

另一种选择是使用base R中的max.col

data.frame(year = dat$year, category = names(dat[-1])[max.col(dat[-1])])
#  year category
#1 2000     cat3
#2 2001     cat1
#3 2002     catN
#4 2018     cat2
max.col函数可以在你的数据中(第一列除外)找到所有值为1的位置,并返回一个数字向量,该向量用于对列名进行子集筛选,同样地,第一列也被排除在外。
此内容由Rui Barradas提供。

1
一个简单的解决方案:

# your data
data <-data.frame(year =c(2016,2017,2018),
                  cat.1=c(0,1,0),
                  cat.2=c(0,0,1),
                  cat.3 =c(1,0,0))

# a nice library 
library(reshape2)

# from wide to long
filtered <- melt(data, id = 'year') %>% filter(value>0) 

# remove the useless column
filtered <- filtered[,1:2]
    > filtered
  year variable
1 2017    cat.1
2 2018    cat.2
3 2016    cat.3

1
这基本上是一个从宽格式转换为长格式的数据框技巧。我将使用reshape2包来完成这项任务。
然后选择value == 1的行。
result <- reshape2::melt(dat, id.vars = "year")
result <- result[result$value == 1, 1:2]
result <- result[order(result[[1]]), ]
names(result)[2] <- "category"
row.names(result) <- NULL

result
#  year category
#1 2000     cat3
#2 2001     cat1
#3 2002     catN
#4 2018     cat2

数据。

dat <- read.table(text = "
year cat1 cat2 cat3  catN
2000  0    0    1   0
2001  1    0    0   0
2002  0    0    0   1
2018  0    1    0   0
", header = TRUE)

1
另一个使用基本R选项的方法,使用stack
subset(data.frame(year = df$year, stack(df, select = -year)), values == 1)[-2]
#   year  ind
#2  2001 cat1
#8  2018 cat2
#9  2000 cat3
#15 2002 catN

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接