如何使用dplyr将分组数据写入不同的文件?

22

我试图使用dplyr的group_by函数对数据框进行分组,并创建每个组的独立的.csv文件。目前我有以下代码:

by_cyl <- group_by(mtcars, cyl)
do(by_cyl, write_csv(., "test.csv"))

正如预期的那样,这将编写一个只包含最后一组数据的单个 .csv 文件。我该如何修改它以编写多个 .csv 文件,并且每个文件名都包含cyl?

4个回答

33

使用 dplyr_0.8.0 ,可以通过group_bygroup_walk来实现此操作。

library(dplyr)
library(readr)
mtcars %>%
   group_by(cyl) %>%
   group_walk(~ write_csv(.x, paste0(.y$cyl, "test.csv")))

2
我不知道这个函数的存在,谢谢你的回答! - Andrew Brēza
1
现在这样做简单多了!谢谢。 - damo

21

您可以按照以下方式将csv写入过程包装在自定义函数中。请注意,该函数必须返回一个data.frame,否则会返回错误Error: Results are not data frames at positions

这将返回3个名为"mtcars_cyl_4.csv"、"mtcars_cyl_6.csv"和"mtcars_cyl_8.csv"的csv文件。

customFun  = function(DF) {
write.csv(DF,paste0("mtcars_cyl_",unique(DF$cyl),".csv"))
return(DF)
}

mtcars %>% 
group_by(cyl) %>% 
do(customFun(.))

正是我所需要的! 顺便说一下,在我的实际情况中,我正在按两个变量进行分组;结果证明,按照分组的顺序确实非常重要。对于这个例子,“cyl”必须是第一个分组才能起作用。 - Nat
漂亮的函数包装器!谢谢! - philiporlando

7
以下代码可以正常工作(你可以跳过自定义函数)
library(dplyr)
library(readr)
group_by(mtcars, cyl) %>%
  do(write_csv(., paste0(unique(.$cyl), "test.csv")))

我在使用@OdeToMyFiddle的答案时没有问题,但我遇到了这个错误:“Error: Results are not data frames at positions: 1, 2, 3, 4, 5, 6, 7”。 - val

4

如果您愿意使用data.table,有一种稍微简洁一些的方法可以实现。

require(data.table)
# Because this is a built in table we have to make a copy first
mtcars <- mtcars 
setDT(mtcars) # convert the data into a data.table

mtcars[, write.csv(.SD, paste0("mtcars_cyl_", .BY, ".csv")), by = cyl]

请注意,生成的表格不会包含 cyl 列(因为它已经存储在文件名中,这是多余的,但也许您出于其他原因需要保留它)。
如果您想要 cyl 作为列被包括在输出结果中,可以使用:
mtcars[, write.csv(c(.BY,.SD), paste0("mtcars_cyl_", .BY, ".csv")), by=cyl]

如果在未复制内置表的情况下将其转换为data.table,则会出现错误。以下是您会收到的错误消息:“Error in setDT(mtcars) : Can not convert 'mtcars' to data.table by reference because binding is locked. It is very likely that 'mtcars' resides within a package (or an environment) that is locked to prevent modifying its variable bindings. Try copying the object to your current environment, ex: var <- copy(var) and then using setDT again." - Rob Donnelly
感谢您的建议,Rich。 - Rob Donnelly
1
@RobDonnelly,如果你真的想提高代码的速度,请用fwrite替换write.csv,这是本地data.table.csv的方法。它非常快,因为它可以并行工作。 - rafa.pereira
@RobDonnelly 你能在你的代码中使用 fwrite() 而不是使用 write.csv() 吗?当应用于大型数据集时,前者更快。 - Miao Cai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接