Write multiple csv files by group

Viewed 2483

I would like to divide my dataframe into multiple csv files by group "Rkey". For example, the sample data below would result in 3 different csv files being made, one for each unique Rkey group: R01, R02, and R03. Each of the three files would only include the rows belonging to its respective group. The names of these files can match the Rkey group name.

How should I work this out? many thanks!

Pkey    Rkey    Var1     Var 2
R01_1   R01  0.0000861   0.0021976 
R01_2   R01  0.0157098   0.0415425 
R01_3   R01  0.0142236   0.0316527 
R01_4   R01  0.0000328   0.3496403 
R01_5   R01  0.0122406   0.1739126
R02_1   R02  0.0000856   0.0000915 
R02_2   R02  0.0002946   0.0006898 
R02_3   R02  0.0209878   0.0209901 
R02_4   R02  0.0001359   0.0008970 
R02_5   R02  0.0011158   0.0023558 
R02_10  R02  0.0015220   0.0019581 
R02_11  R02  0.0004664   0.0385724 
R02_12  R02  0.0000095   0.3224465 
R03_1   R03  0.0008863   0.0056300 
R03_2   R03  0.0000021   0.0000185 
R03_3   R03  0.0000170   0.0001655 
5 Answers

Consider by:

by(df, df$Rkey, FUN=function(i) write.csv(i, paste0(i$Rkey[1], ".csv")))

How about this?

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

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

Or, this.

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]


One solution using tidyverse ecosystem

Using readr to load your data

library(readr)
df <- read_delim("Pkey Rkey Var1 Var2
R01_1 R01 0.0000861 0.0021976
R01_2 R01 0.0157098 0.0415425
R01_3 R01 0.0142236 0.0316527
R01_4 R01 0.0000328 0.3496403
R01_5 R01 0.0122406 0.1739126
R02_1 R02 0.0000856 0.0000915
R02_2 R02 0.0002946 0.0006898
R02_3 R02 0.0209878 0.0209901
R02_4 R02 0.0001359 0.0008970
R02_5 R02 0.0011158 0.0023558
R02_10 R02 0.0015220 0.0019581
R02_11 R02 0.0004664 0.0385724
R02_12 R02 0.0000095 0.3224465
R03_1 R03 0.0008863 0.0056300
R03_2 R03 0.0000021 0.0000185
R03_3 R03 0.0000170 0.0001655", delim = " ")

Using tidyr to nest your data by group creating a list colunm you can play with. Then using purrr to iterate over the column of the data.frame. pwalk allows you to iterate through a list to do some function with no results like writing a CSV. I created a tempdir for writing some files.

library(tidyr)
library(purrr)
temp_dir <- tempfile()
dir.create(temp_dir)

df %>%
  nest(-Rkey) %>% 
  pwalk(function(Rkey, data) write_csv(data, file.path(temp_dir, paste0(Rkey, ".csv"))))

We check files are created

list.files(temp_dir)
#> [1] "R01.csv" "R02.csv" "R03.csv"

And that they contains some data

read_lines(list.files(temp_dir, full.names = T)[1])
#> [1] "Pkey,Var1,Var2"            "R01_1,8.61e-5,0.0021976"  
#> [3] "R01_2,0.0157098,0.0415425" "R01_3,0.0142236,0.0316527"
#> [5] "R01_4,3.28e-5,0.3496403"   "R01_5,0.0122406,0.1739126"

We just delete the temp folder we have created

unlink(temp_dir, recursive = T)

You may want to to use the subset function.

 subset(dataframe_name, Rkey=val)

to get the list of the unique values, use the "unique" function on the RKey column which you can select by:

dataframe_name[2]

Now you just take each subset and do whatever you want with it :)

Your final code should look like:

unique_rkeys = unique(dataframe_name[2])
for(key in unique_keys){
    df_subset = subset(dataframe_name, Rkey=key)
    //do stuff with the subset...
}

A simple way:

sapply(unique(df$Rkey), function(x) 
  write.csv(df[df$Rkey==x,],paste0("~/YourPathHere/",x,".csv"),row.names=FALSE))
Related