【问题标题】:How to use purrr with dplyr to filter list elements and export lists into Excel如何使用 purrr 和 dplyr 过滤列表元素并将列表导出到 Excel
【发布时间】:2016-07-22 15:12:36
【问题描述】:

我对在 R 中使用列表还很陌生,并且有一个快速的问题,也涉及使用 purrr。下面以太小的样本数据框为例。

Client1 <- c("John","Chris","Yutaro","Dean","Andy")
Animals <- c("Cat","Cat","Dog","Rat","Bird")
Living <- c("House","Condo","Condo","Apartment","House")
Data1 <- data.frame(Client1,Animals,Living)

Client1 <- c("John","Chris","Yutaro","Dean","Andy")  
Animals2 <- c("Cat","Dog","Dog","Rat","Cat")
Living2 <- c("House","Apartment","Apartment","Family","Apartment")
Data2 <- data.frame(Client1,Animals2,Living2)

如果您可以包含如何一次重命名列表元素而不是使用下面的两行代码,则将获得奖励:

names(Data1)[1:3] <- c("Client","Animals","Living")
names(Data2)[1:3] <- c("Client","Animals","Living")

接下来,如果我想通过Animals 过滤每个数据框,然后使用以下两行代码将每个数据框导出到 Excel 电子表格中:

Data1 %>% filter(Animals=="Cat") %>% write.csv(.,file="Data1.csv")
Data2 %>% filter(Animals=="Cat") %>% write.csv(.,file="Data2.csv")

但是,为了提高效率,我可以将两个数据帧加入 list 并使用 purrr 同时过滤每个数据帧。

DataList <- list(Data1,Data2)
DataList %>% map(~filter(.,Animals=="Cat"))

对于上面的代码,我将为每个动物使用多个~filter 行,所以不确定是否有更有效的方法可以避免在仍然使用purrrdplyr 的同时编写许多不同的代码行?

另外,我如何将write.csvpurrr 一起使用。我可以将列表导出到一个电子表格中,但我不确定如何分解列表以便正确导出。此外,我可以将每个列表元素导出到单独的电子表格中。很高兴看到这两种情况的解决方案。

【问题讨论】:

  • 您是否希望每个数据集中的每种动物都有一个单独的 csv 文件?在您的实际情况下,您的数据集是否如此相似(即它们包含相同的变量)?

标签: r dplyr purrr


【解决方案1】:

如果我正确理解您的问题,您想为两个数据框的每个Animals 编写一个单独的文件:

DataList <- list(Data1, Data2)

library(purrr)


a <- DataList %>% map(., function(x) { 
        colnames(x) <- c("Client","Animals","Living")
        x
}) %>% map(., function(x) { 
        split(x, x$Animals)
}) %>% flatten(.)

names(a) <- paste0("Data", (1:length(a)))


lapply(1:length(a), function(x) write.csv(a[[x]], 
                                            file = paste0(names(a[x]), ".csv"),
                                            row.names = FALSE))

我们首先将两个数据帧转储到DataList,然后将两个数据帧的列重命名为第一个map,然后将split 两个数据帧都改名为Animals,最后flatten嵌套列表。

我希望我可以在不破坏链条的情况下做到这一点,但我找不到其他方法。

从这里开始,我们首先重命名列表的元素,然后使用lapply 循环遍历列表中的所有元素,并对每个元素应用write.csv

您提到了Excel - 您可以轻松地将write.csv 替换为从R 写入excel 文件的任何函数

【讨论】:

    【解决方案2】:

    这是一种选择,涉及在重新拆分之前将两个数据集绑定在一起。

    library(purrr)
    library(dplyr)
    
    DataList %>%
        map(~setNames(.x, c("Client","Animals","Living"))) %>%
        setNames(c("Data1", "Data2")) %>%
        bind_rows(.id = "id") %>%
        split(list(.$id, .$Animals), drop = TRUE) %>%
        map(~select(.x, -id) %>% 
                   write.csv(file = paste0(unique(.x$id), unique(.x$Animals), ".csv"),
                                    row.names = FALSE))
    

    第一行map 显示如何通过setNames 一次重命名列表中所有数据集的列。

    DataList %>%
        map(~setNames(.x, c("Client","Animals","Living")))
    

    然后我通过setNames 在列表中设置数据集的名称。在通过 dplyr 的 bind_rows 将数据集堆叠到单个 data.frame 中时,这些名称将添加为新列 id

    setNames(c("Data1", "Data2")) %>%
    bind_rows(.id = "id")
    

    最后一步是将合并后的 data.frame 按idAnimal 拆分,然后将每个拆分写入单独的 csv 文件。从数据集中提取信息以按数据集和动物命名单个文件(这就是命名DataList 的元素的原因)。在编写文件之前,我通过select 删除了id 变量,因为它可能与您的需求无关。

    split(list(.$id, .$Animals), drop = TRUE) %>%
    map(~select(.x, -id) %>% 
                write.csv(file = paste0(unique(.x$id), unique(.x$Animals), ".csv"),
                                    row.names = FALSE))
    

    这一切都可以在不将它们放入单个 data.frame 的情况下完成,但我在最后命名文件时遇到了麻烦。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-28
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多