【问题标题】:R - Unlist Data_frame column of lists in tidy mannerR - 以整洁的方式取消列出列表的 Data_frame 列
【发布时间】:2023-03-07 13:02:01
【问题描述】:

我在数据框中有数据,其中一列是列表。这是一个例子:

rand_lets <- function(){
  sample(letters[1:26], runif(sample(1:10, 1), min=5, max=12))
}

example_data <- data.frame(ID = seq(1:5),
                           location = LETTERS[1:5],
                           observations = I(list(rand_lets(),
                                                 rand_lets(),
                                                 rand_lets(),
                                                 rand_lets(),
                                                 rand_lets())))

我正在寻找一种优雅的 tidyverse 方法来取消列出列表列,以便将列表中的每个元素分隔到一个新列中。例如,第一行如下所示:

ID location observations  observations.1  observations.3  observations.3  observations.4  observations.5  observations.6  observations.7  observations.8  observations.9  
1        A  "y"           "b"             "m"             "u"             "x"             "j"             "t"             "i"             "v"             "w"

当然,列表条目可能有不同的长度,所以空单元格应该是 NA。

这是怎么做到的?

【问题讨论】:

  • 长格式对于不规则数据几乎肯定更有用,但是如果你真的想直接进入宽格式,你可以在列表列中构造数据:example_data %&gt;% mutate(observations = map(observations, ~as_data_frame(t(.x)))) %&gt;% unnest()
  • 太棒了。这是map() 的巧妙使用。我同意长格式更有用,但我想在教程中使用我的数据集,从宽格式到长格式是很好的第一课。

标签: r dataframe tidyr tidyverse


【解决方案1】:

如果您想将数据保持为“长”格式,您可以这样做:

example_data %>% unnest(observations) 
   ID location observations
1   1        A            e
2   1        A            x
3   1        A            w
...
44  5        E            u
45  5        E            o
46  5        E            z

要将数据传播为“宽”格式,如您的示例所示,您可以这样做:

library(stringr)

example_data %>% unnest(observations) %>%
  group_by(location) %>%
  mutate(counter=paste0("Obs_", str_pad(1:n(),2,"left","0"))) %>%
  spread(counter, observations)
     ID location Obs_01 Obs_02 Obs_03 Obs_04 Obs_05 Obs_06 Obs_07 Obs_08 Obs_09 Obs_10 Obs_11
* <int>   <fctr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>
1     1        A      e      x      w      c      s      j      k      t      z   <NA>   <NA>
2     2        B      k      u      d      h      z      x   <NA>   <NA>   <NA>   <NA>   <NA>
3     3        C      v      z      m      o      s      f      n      c      r      u      b
4     4        D      z      i      m      s      a      v      n      r      e      t      x
5     5        E      f      b      g      h      a      d      u      o      z   <NA>   <NA>

【讨论】:

  • 真棒@eipi10 - 你能解释为什么它不需要group_by(ID, location) - 在我看来,按ID分组是隐含的。顺便说一句,counter=sprintf("Obs_%02i", 1:n())` 可能是格式化标题的一种更简洁的方式。
  • 如果每个位置有多个 ID,反之亦然,请使用 group_by(ID, location)
猜你喜欢
  • 2017-11-14
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
  • 2020-12-29
  • 2018-12-22
  • 2016-10-07
  • 2022-01-09
  • 1970-01-01
相关资源
最近更新 更多