R:在组和子组中切片数据帧记录的最有效方法(通过目录和 CSV)
R: Most efficient way to slice data frame records in groups and sub-groups (via directories and CSV)
给定以下示例数据 (R data frame
),我想为每个组创建文件夹,包含每个子组的文件夹,(最终)包含一个具有相应值的 CSV 文件 val1
, 使用 R.
Grp <- c("A", "A", "A", "B", "B", "B")
Subgrp <- c("k", "l", "m", "n", "n", "n")
val1 <- c(1.1, 3.2, 4.5, 5.6, 6.7, 7.7)
df <- data.frame(Grp, Subgrp, val1)
这是我迄今为止尝试过的方法,为每个子组创建一个 CSV 文件。
by(df, df$Subgrp, FUN=function(i) write.csv(i,paste0("C:/Temp/",i$Subgrp[1], ".csv")))
我需要为大数据框迭代这个。实现这一目标的最有效方法是什么?我愿意接受基于循环和 dpyr 的建议。
你很接近。
我的解读:
- "为每个组创建文件夹,包含每个子组的文件夹":使用
.../A/k
和 .../B/n
等目录
- "具有相应值的 CSV 文件
val1
":保存为 CSV 时从框架中删除 Grp
和 Subgrp
列. (如果不是这个,则将 subset(...)
替换为下面的 i
。)
basepath <- "c:/Temp"
# pre-create directories
for (p in unique(file.path(basepath, df$Grp, df$Subgrp))) dir.create(p, recursive = TRUE)
by(df, df$Subgrp, FUN=function(i) {
write.csv(subset(i, select = -c(Grp, Subgrp)),
file.path(basepath, i$Grp[1], i$Subgrp[1], "value.csv"),
row.names = FALSE)
})
# df$Subgrp: k
# NULL
# ------------------------------------------------------------
# df$Subgrp: l
# NULL
# ------------------------------------------------------------
# df$Subgrp: m
# NULL
# ------------------------------------------------------------
# df$Subgrp: n
# NULL
lf <- list.files(".", pattern = "csv$", recursive = TRUE, full.names = TRUE)
lf
# [1] "./A/k/value.csv" "./A/l/value.csv" "./A/m/value.csv" "./B/n/value.csv"
read.csv(lf[1])
# val1
# 1 1.1
由于 by
的 return 值无关紧要,您可以将其包装在 invisible(.)
中或捕获并忽略输出 ign <- by(..)
.
我宁愿使用lapply
这样你可以方便地使用子组的名称。
lapply(df$Subgrp, \(x) write.csv(subset(df, Subgrp == x), file=sprintf('C:/Temp/%s.csv', x)))
使用 tidyverse:
df %>%
unite(file, Grp, Subgrp, sep='/')%>%
group_by(file = paste0(file, '.csv'))%>%
summarise(write.csv(cur_data(),
if(dir.exists(dirname(file[1]))) file[1]
else {dir.create(dirname(file[1]),recursive = T);file[1]},row.names = FALSE))
给定以下示例数据 (R data frame
),我想为每个组创建文件夹,包含每个子组的文件夹,(最终)包含一个具有相应值的 CSV 文件 val1
, 使用 R.
Grp <- c("A", "A", "A", "B", "B", "B")
Subgrp <- c("k", "l", "m", "n", "n", "n")
val1 <- c(1.1, 3.2, 4.5, 5.6, 6.7, 7.7)
df <- data.frame(Grp, Subgrp, val1)
这是我迄今为止尝试过的方法,为每个子组创建一个 CSV 文件。
by(df, df$Subgrp, FUN=function(i) write.csv(i,paste0("C:/Temp/",i$Subgrp[1], ".csv")))
我需要为大数据框迭代这个。实现这一目标的最有效方法是什么?我愿意接受基于循环和 dpyr 的建议。
你很接近。
我的解读:
- "为每个组创建文件夹,包含每个子组的文件夹":使用
.../A/k
和.../B/n
等目录
- "具有相应值的 CSV 文件
val1
":保存为 CSV 时从框架中删除Grp
和Subgrp
列. (如果不是这个,则将subset(...)
替换为下面的i
。)
basepath <- "c:/Temp"
# pre-create directories
for (p in unique(file.path(basepath, df$Grp, df$Subgrp))) dir.create(p, recursive = TRUE)
by(df, df$Subgrp, FUN=function(i) {
write.csv(subset(i, select = -c(Grp, Subgrp)),
file.path(basepath, i$Grp[1], i$Subgrp[1], "value.csv"),
row.names = FALSE)
})
# df$Subgrp: k
# NULL
# ------------------------------------------------------------
# df$Subgrp: l
# NULL
# ------------------------------------------------------------
# df$Subgrp: m
# NULL
# ------------------------------------------------------------
# df$Subgrp: n
# NULL
lf <- list.files(".", pattern = "csv$", recursive = TRUE, full.names = TRUE)
lf
# [1] "./A/k/value.csv" "./A/l/value.csv" "./A/m/value.csv" "./B/n/value.csv"
read.csv(lf[1])
# val1
# 1 1.1
由于 by
的 return 值无关紧要,您可以将其包装在 invisible(.)
中或捕获并忽略输出 ign <- by(..)
.
我宁愿使用lapply
这样你可以方便地使用子组的名称。
lapply(df$Subgrp, \(x) write.csv(subset(df, Subgrp == x), file=sprintf('C:/Temp/%s.csv', x)))
使用 tidyverse:
df %>%
unite(file, Grp, Subgrp, sep='/')%>%
group_by(file = paste0(file, '.csv'))%>%
summarise(write.csv(cur_data(),
if(dir.exists(dirname(file[1]))) file[1]
else {dir.create(dirname(file[1]),recursive = T);file[1]},row.names = FALSE))