【问题标题】:dataframe column containing lists extracted as columns of the same dataframe包含提取为同一数据框列的列表的数据框列
【发布时间】:2018-05-18 13:18:36
【问题描述】:

我有一个包含 3 列的数据框。其中一列(第二列)包含每个单元格的值列表。这里dput样本数据:

   df <- structure(list(column1 = c("HEATER", "COOLER"), column2 = list(structure(list(
        insidelist = structure(list(es = list("1"), en = list("00"), la = list(
            "01")), .Names = c("es", "en", "la"))), .Names = "insidelist"), 
        structure(list(insidelist = structure(list(es = list("1"), en = list(
            "01"), la = list("01")), .Names = c("es", "en", "la"))), .Names = "insidelist")), 
        column3 = c("88", "31")), .Names = c("column1", "column2", "column3"
    ), row.names = c(NA, -2L), class = "data.frame")

给出这个df:

  column1   column2     column3
1  HEATER   1, 00, 01      88
2  COOLER   1, 01, 01      31

如何从第二列中获取该值列表作为原始数据框的列?

期望的输出:

  column1   column2 Column3 column4 column5
1  HEATER     1       00       01      88
2  COOLER     1       01       01      31

【问题讨论】:

  • 或许df %&gt;% mutate(out = map(column2, ~ .x %&gt;% transpose %&gt;% unlist %&gt;% as.list %&gt;% as_tibble)) %&gt;% unnest %&gt;% select(-column2)
  • 稍作改动即可获得所需的列名:df %&gt;% mutate(out = map(column2, ~data.frame(new = t(unlist(.)), stringsAsFactors = F))) %&gt;% unnest() %&gt;% select(column1, matches("new"), column3) %&gt;% setNames(paste0("column", 1:ncol(.)))

标签: r dplyr


【解决方案1】:

不要误会我的意思,我和这里的每个人一样都喜欢整洁的做事方式,而且很多人正在学习 R 编程,这要归功于它,它走上了一条更简单的道路,但我认为有时 当你有锤子一切看起来都像钉子

Tidyverse 有很多优点,但也有一些缺点,其中之一似乎掩盖/隐藏了 R 语言的基础知识。 在这种情况下,最强大和“人类可读的”解决方案(恕我直言)是以可读的方式混合方法。

我们来看看。 首先我们摆脱嵌套列表,将它们转换为数据框:

df$column2 <- data.frame(matrix(unlist(df$column2), nrow=nrow(df), byrow=T))

> df
  column1 column2.X1 column2.X2 column2.X3 column3
1  HEATER          1         00         01      88
2  COOLER          1         01         01      31

然后提取内部数据框(column2)并与原始df并排放置:

df <- cbind(select(df,-column2), df$column2)

选择/重命名列是一项微不足道的任务。这里是绑定后的例子:

df <- cbind(df, df$column2) %>%
      select(Column1=1, Column2=4, Column3=5, Column4=6, Column5=3)

这给了我们想要的输出:

> df

  Column1 Column2 Column3 Column4 Column5
1  HEATER       1    00      01      88
2  COOLER       1    01      01      31

投入整洁的代码有时会导致解决方案不那么整洁。我知道很多人都是这样学习 R 的,但是聪明的程序员应该警惕如果你急于对每个问题都没有考虑基础 R 的问题进行 tidyverse,这可能会导致黑暗的地方。

【讨论】:

    【解决方案2】:

    我们可以的

    library(tidyverse)
    df %>% 
      mutate(out = map(column2, ~ .x %>%
                                  transpose %>%
                                  unlist %>%
                                  as.list %>% 
                                  as_tibble)) %>% 
             unnest %>% 
             select(-column2)
    

    【讨论】:

      【解决方案3】:

      这是我的尝试 - 不像 akrun 和 AntoniosK 那样简洁,但可能更具可读性:

      df %>% 
        unnest(column2) %>% 
        mutate(lengths = map_int(column2, ~ length(unlist(.x))),
               column2 = map_chr(column2, ~ glue::collapse(unlist(.x), sep = ',') )) %>% 
        separate(column2, sep = ',', into = paste('temp', seq(1,max(.$lengths)), sep = '_')) %>%
        select(column1, starts_with('temp'), column3) %>%
        setNames(paste0("column", 1:ncol(.)))
      

      请注意 - 看起来 cmets 中的答案运行得更快一些,所以如果您使用的是大型数据集 - 使用这些可能是明智的。

      【讨论】:

        猜你喜欢
        • 2016-11-02
        • 2021-01-11
        • 1970-01-01
        • 1970-01-01
        • 2021-12-06
        • 1970-01-01
        • 2019-11-10
        • 1970-01-01
        • 2018-09-16
        相关资源
        最近更新 更多