【问题标题】:Convert R data frame into list of vectors将 R 数据帧转换为向量列表
【发布时间】:2019-03-19 02:29:22
【问题描述】:

我有一个数据框(从 Excel 工作表中导入,我在其中逐行编写了字符串列表)并希望将行转换为向量列表,其中每个向量包含该行的非缺失单元格值:

例如:

#Sample data frame
dfX <- data.frame(C0 = c(1,2,3),
              C1 = c("Apple","Apple","Pear"),
              C2 = c("Banana","Orange", "Lemon"),
              C3 = c("Pear","Melon", ""))

这将用于生成以下列表:

myList = list(c("Apple","Banana", "Pear"),
          c("Apple","Orange", "Melon"),
          c("Pear","Lemon"))

请注意,第三个向量被截断为两个元素,因为单元格包含一个空字符串。另请注意,索引 (C0) 已删除。

我见过一些将数据框转换为矩阵并使用 split 函数将结果粘贴到全局环境中的示例,例如

list2env(setNames(split(as.matrix(dfX),
                    row(dfX)), paste0("Row",1:3)),
                    envir=.GlobalEnv)

但我想知道是否有 (a) 一个更新的 tidyverse 函数来处理这个问题,以及 (b) 一种直接填充到列表的方法(我稍后想针对该列表应用一个函数)。如果可能,还希望在进入列表的过程中处理缺失值!

【问题讨论】:

  • data.frame 实际上是一个向量列表。所以,class(dfX) &lt;- "list"
  • 或as.list(dfX)。无论哪种方式,首先将空字符串转换为NA_character_ 可能会让您的生活更轻松。如果您从 csv 读取数据,请注意方便的参数 na.strings 在导入期间执行此操作。
  • @Khashaa 这不会重现 OP 的预期输出; OP 在逐行(而不是逐列)操作之后。您的解决方案将 data.frame 转换为列向量的 list。 OP 想要一个 list 的行向量。
  • @MauritsEvers 没有注意到行已转置。 gather(dfX, var, val, -C0) %&gt;% spread(C0, val) %&gt;% map(c)`

标签: r tidyverse


【解决方案1】:

由于您对tidyverse 方式感兴趣,因此一种选择是

library(tidyverse)

dfX %>%
  group_split(C0) %>% #Or use split(.$C0) if `dplyr` is not updated
  map(~discard(flatten_chr(.), . == "")[-1])

#[[1]]
#[1] "Apple"  "Banana" "Pear"  

#[[2]]
#[1] "Apple"  "Orange" "Melon" 

#[[3]]
#[1] "Pear"  "Lemon"

group_split 在dplyr 0.8.0 中可用。这还假设您在每一行中都有唯一的C0,并且对于每一行我们discard 任何等于空字符串(“”)的值。


或者在基本 R 中,split 和 lapply 的组合也可以。

lapply(split(dfX[-1], dfX$C0), function(x) x[x != ""])

#$`1`
#[1] "Apple"  "Banana" "Pear"  

#$`2`
#[1] "Apple"  "Orange" "Melon" 

#$`3`
#[1] "Pear"  "Lemon"

另一个基本 R 选项是 apply 和 MARGIN = 1

apply(dfX[-1], 1, function(x) x[x!= ""])

【讨论】:

  • 我尝试了 tidyverse 版本,但我的 dplyr 版本没有更新,注释版本抛出错误。使用第一个基本 R 解决方案(拆分和 lapply),它完成了工作。我有点惊讶 tidyverse 没有将行(或列)对象转换为字符串向量的功能?
  • @BrisbanePom 这就是引入group_split 的原因。很奇怪,它不起作用。也许是因为它是一个因素?你能不能把它转换成字符然后检查。 dfX %&gt;% mutate_all(as.character) %&gt;% split(.$C0) %&gt;% map(~discard(flatten_chr(.), . == "")[-1]) 在提供的样本数据上为我工作。
【解决方案2】:

基本 R 选项是 by

by(dfX, dfX$C0, function(x) unlist(x[x != ''][-1]))
#dfX$C0: 1
#[1] "Apple"  "Banana" "Pear"
#------------------------------------------------------------
#dfX$C0: 2
#[1] "Apple"  "Orange" "Melon"
#------------------------------------------------------------
#dfX$C0: 3
#[1] "Pear"  "Lemon"

by 返回一个“穿着”列表,忽略属性,这与您预期的myList 相同。

【讨论】:

  • 没问题+1,by是split + lapply在一个函数中的组合。
猜你喜欢
  • 2017-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-24
  • 1970-01-01
  • 2016-08-14
  • 1970-01-01
  • 2021-01-18
相关资源
最近更新 更多