我有一个包含286项的清单。
length(l)
[1] 286
我想知道的是为每个列表的.csv子集创建一个单独的.csv文件
split_csv <- function(df, list) {
setwd("dir")
for (i in list)
#print(i)
df_temp <- df[df$club == i, ]
name <- paste0("club_", i, ".csv")
write.csv(df_temp, name)
setwd("original_dir")
}
但事情是我现在只获得.csv文件!奇怪的是当我取消注释#print(i)
它确实给了我列表中的所有项目(所以我假设循环正在工作。
有什么想法吗?
答案 0 :(得分:3)
您的代码的主要问题是您不使用花括号将多个语句放在循环中。从R的角度来看,仅在循环内评估第一行(df_temp <- df[df$club == i, ]
)。程序的其余部分 - 包括实际将内容写入文件 - 仅在循环结束后完成。因为在循环内创建的变量将被添加到全局环境中并且在循环外部可用,所以不会引发错误。但是,实际上,您的文件编写代码仅在循环的最后一次迭代时执行。
修复此问题很简单:
set.seed(123)
l <- data.frame(club=sample(LETTERS[1:10], 286, TRUE),
visitors=as.integer(runif(286, 100, 1000))
)
split_csv <- function(df, list) {
setwd("dir")
for (i in list) {
#print(i)
df_temp <- df[df$club == i, ]
name <- paste0("club_", i, ".csv")
write.csv(df_temp, name)
}
setwd("..")
}
split_csv(l, LETTERS[1:3])
list.files("dir/")
# [1] "club_A.csv" "club_B.csv" "club_C.csv"
但是,让我们以您的问题为契机,了解如何改进此代码。
by
function可用于将data.frame拆分为在给定因子中具有相同值的子集(或因子,但让它保持简单)。您可以在该子集上运行任何功能 - 包括自定义(和匿名)功能。
split_csv2 <- function(df, list) {
by(df, df$club, function(x) {
# `x` is subset of df with one value in `club`
# assign current "club" value for further reference
i <- x[1, "club"]
# don't do anything else if current club is not in list of allowed clubs
if (! i %in% list) return()
name <- paste0("dir/club_", i, ".csv")
write.csv(x, name)
}
)
}
invisible(split_csv2(l, LETTERS[2:4])) # discard output - it's not helpful anyway
list.files("dir/")
# [1] "club_B.csv" "club_C.csv" "club_D.csv"
这种方法有两个主要优点:
此外:
list
function,这是一个基本的R数据结构。在更复杂的情况下,这可能会导致意外行为并且难以调试问题。更好地避免这一点。