如何使用purrr和dplyr过滤列表元素并将列表导出到Excel

时间:2016-07-22 15:12:37

标签: r dplyr purrr

我很擅长使用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行,因此不确定是否有一种更有效的方法可以避免在使用purrr和{dplyr和{write.csv时编写许多不同的代码行{1}}?

此外,如何将purrr^[A-Za-z]*[!"\#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~]?[A-Za-z]*$ 一起使用。我可以将列表导出到一个电子表格中,但我不确定如何拆分列表以便正确导出。此外,我可以将每个列表元素导出到单独的电子表格中。很高兴看到这两种情况的解决方案。

2 个答案:

答案 0 :(得分:3)

如果我理解你的问题,你想为两个数据框的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重新命名两个数据框的列,然后splitAnimals数据框重命名为flatten },最后是lapply嵌套列表。

我希望我能在不打破链条的情况下做到这一点,但我无法找到另一种方式。

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

您提到write.csv - 您可以使用R

编写Excel文件的任何功能轻松替换Import-Csv 'File1.csv' | ForEach { [pscustomobject]@{ Date = $_.Date -as [datetime] Description = $_.Description Amount = $_.Amount -as [int] } }

答案 1 :(得分:3)

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

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的元素的原因)。我在写文件之前通过id删除了select变量,因为这可能与您的需求无关。

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的情况下完成,但是我在最后命名文件时遇到了麻烦。