使用dplyr在R中创建包含列表元素的数据框。

5
这是我的数据框:
    df<-list(structure(list(Col1 = structure(1:6, .Label = c("A", "B", 
"C", "D", "E", "F"), class = "factor"), Col2 = structure(c(1L, 
2L, 3L, 2L, 4L, 5L), .Label = c("B", "C", "D", "F", "G"), class = "factor")), class = "data.frame", row.names = c(NA, 
-6L)), structure(list(Col1 = structure(c(1L, 4L, 5L, 6L, 2L, 
3L), .Label = c("A", "E", "H", "M", "N", "P"), class = "factor"), 
    Col2 = structure(c(1L, 2L, 3L, 2L, 4L, 5L), .Label = c("B", 
    "C", "D", "F", "G"), class = "factor")), class = "data.frame", row.names = c(NA, 
-6L)), structure(list(Col1 = structure(c(1L, 4L, 6L, 5L, 2L, 
3L), .Label = c("A", "W", "H", "M", "T", "U"), class = "factor"), 
    Col2 = structure(c(1L, 2L, 3L, 2L, 4L, 5L), .Label = c("B", 
    "C", "D", "S", "G"), class = "factor")), class = "data.frame", row.names = c(NA, 
-6L))) 

我想提取col1 = df [[1]] [1] 作为一个数据框。 然后,我想将此列表的第二个位置的col1合并到df [[1]] [1],然后我将拥有一个具有2列的数据帧。 之后,我想将列表第三个位置的列1合并到具有两列的数据帧中,然后我将拥有一个具有3列的数据帧。
换句话说,我的数据框应该具有3列,即每个条目的第一列。
dplyr包可以帮助我做到这一点吗?
需要帮忙吗?

@SalmanLashkarara 我编辑了问题。 - Laura
5个回答

5
你可以使用lapply一次性提取名为"Col1"的三列。然后设置结果的名称。
col1 <- as.data.frame(lapply(df, '[[', "Col1"))
names(col1) <- letters[seq_along(col1)]

col1
#  a b c
#1 A A A
#2 B M M
#3 C N U
#4 D P T
#5 E E W
#6 F H H

选择任何其他你认为更好的列名。
使用 dplyr 的方法可能是:
df %>% 
  unlist(recursive = FALSE) %>%
  as.data.frame %>%
  select(., starts_with("Col1"))
#  Col1 Col1.1 Col1.2
#1    A      A      A
#2    B      M      M
#3    C      N      U
#4    D      P      T
#5    E      E      W
#6    F      H      H

5

使用purrr中的map_dfc

library(purrr)

map_dfc(df, `[`, 1)

输出:

  Col1 Col11 Col12
1    A     A     A
2    B     M     M
3    C     N     U
4    D     P     T
5    E     E     W
6    F     H     H

甚至只需使用 map_dfc(df, "Col1")map_dfc(df, 1) - Calum You
@CalumYou 两者都会出现错误:Error in cbind_all(x) : Not compatible with STRSXP: [type=NULL]。因为 map(df, 1) 返回的是向量列表,而不是数据框列表。 - acylam
我无法重现此错误,请参见我的补充答案中的 reprex。使用 purrr 0.2.5。 - Calum You
请注意,map_dfc(df, 1)dplyr_0.7.4 中不起作用,但我的解决方案可以。 - acylam

2

使用purrr的简洁元素提取语法,可以按名称或位置指定元素的元素,从而实现对map_dfc的替代用途。例如,第一个等同于:

map_dfc(df, `[[`, 1)

使用[与使用V的不同之处在于,列名不会变成Col1的变体,而是直接获得V名称。这可能更可取,因为像Col11Col12这样的名称可能会令人困惑。

df <- list(structure(list(Col1 = structure(1:6, .Label = c("A", "B", "C", "D", "E", "F"), class = "factor"), Col2 = structure(c(1L, 2L, 3L, 2L, 4L, 5L), .Label = c("B", "C", "D", "F", "G"), class = "factor")), class = "data.frame", row.names = c(NA, -6L)), structure(list(Col1 = structure(c(1L, 4L, 5L, 6L, 2L, 3L), .Label = c("A", "E", "H", "M", "N", "P"), class = "factor"), Col2 = structure(c(1L, 2L, 3L, 2L, 4L, 5L), .Label = c("B", "C", "D", "F", "G"), class = "factor")), class = "data.frame", row.names = c(NA, -6L)), structure(list(Col1 = structure(c(1L, 4L, 6L, 5L, 2L, 3L), .Label = c("A", "W", "H", "M", "T", "U"), class = "factor"), Col2 = structure(c(1L, 2L, 3L, 2L, 4L, 5L), .Label = c("B", "C", "D", "S", "G"), class = "factor")), class = "data.frame", row.names = c(NA, -6L)))

library(purrr)
map_dfc(df, 1)
#> # A tibble: 6 x 3
#>   V1    V2    V3   
#>   <fct> <fct> <fct>
#> 1 A     A     A    
#> 2 B     M     M    
#> 3 C     N     U    
#> 4 D     P     T    
#> 5 E     E     W    
#> 6 F     H     H
map_dfc(df, "Col1")
#> # A tibble: 6 x 3
#>   V1    V2    V3   
#>   <fct> <fct> <fct>
#> 1 A     A     A    
#> 2 B     M     M    
#> 3 C     N     U    
#> 4 D     P     T    
#> 5 E     E     W    
#> 6 F     H     H

这段内容是使用 reprex 包(版本为 v0.2.0)在2018年9月19日创建的。


出现相同的错误:cbind_all(x)中的错误:与STRSXP不兼容:[type=NULL]。我还有purrr_0.2.5。 - acylam
嗯,奇怪。我会进一步调查,但我认为我已经得到了预期的行为,你可以在你那边自由地这样做吗?你能执行 bind_cols(list(1:2, 3:4)) 吗?因为 dfc 只是调用了 dplyr::bind_cols - Calum You
不行,bind_cols(map(df, 1))bind_cols(list(1:2, 3:4))都给我同样的错误。我的解释是元素需要是数据框,这来自于Hadley在这个问题中的回复:https://github.com/tidyverse/dplyr/issues/1389 不确定这是设计还是一个bug。我认为这是设计,因为Hadley一直是类型稳定函数的粉丝。不确定为什么你的可以工作。 - acylam
看起来这也是一个错误,来自于这个问题:https://github.com/tidyverse/purrr/issues/395 - acylam
好的,事实证明我安装的是dplyr_0.7.4版本,仍然存在问题。更新到dplyr_0.7.6版本解决了这个问题。由于bind_cols来自dplyr,更新purrr并没有帮助。也许你应该注意一下,在0.7.6版本之前的dplyr版本上,这种解决方案不起作用。 - acylam
好的,听起来很不错!是的,我有点困惑,因为?bind_cols在示例中提到了“除了数据框之外,您还可以提供向量”。 - Calum You

1
res<-1:nrow(df[[1]][1])

for(i in 1:length(df)){
  print ( as.vector(df[[i]][1]))
  res<-cbind(res,as.data.frame(df[[i]][1]))
}
res$res<-NULL

所以,输出结果是:


  Col1 Col1 Col1
1    A    A    A
2    B    M    M
3    C    N    U
4    D    P    T
5    E    E    W
6    F    H    H

0
使用 dplyr
library(dplyr)
df %>% 
  sapply('[[',1) %>%
  as.data.frame
#returns
  V1 V2 V3
1  A  A  A
2  B  M  M
3  C  N  U
4  D  P  T
5  E  E  W
6  F  H  H

1
这基本上是Rui的答案,只不过使用了管道符号,与dplyr无关。 - acylam
@avid_useR 我明白了,那我应该把它删除吗? - Chriss Paul
1
除非你有其他的东西要展示,否则我认为这对Rui的回答没有任何价值。 - acylam

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