似乎每个涉及R中循环的问题都会遇到“循环错误”和“你做错了”,建议使用list
或tapply
或诸如此类。
我正在学习R,并且已经实现了以下循环来为每个因子级别创建图像文件,每次运行时因子级别的#都会改变:
for(i in unique(df$factor)) {
lnam <- paste("test_", i, sep="")
assign(lnam, subset(df, factor==i))
lfile <- paste(lnam, ".png", sep="")
png(file = lfile, bg="transparent")
with(get(lnam), hist(x, main = paste("Histogram of x for ", i, " factor", sep="")))
dev.off()
}
这很有效。我想将它扩展为可能对这些子组(也输出到文件)等进行各种测试。
这是循环的有效合法使用吗?或者是否有一种优选的方法来涂抹这只猫?
答案 0 :(得分:7)
一般来说,循环没有任何问题。有时,特别是当您处理文件或调用函数的副作用而不是输出时,循环比*apply
调用更容易理解。但是,当您使用循环来模拟可以进行矢量化的操作时,它通常会慢得多,因此建议避免它们。
举个具体例子,我会发表以下评论:
levels(factor)
而不是unique(factor)
会更直接。考虑到这一点:
for(i in levels(df$factor))
{
lf <- paste("test_", i, ".png", sep="")
png(file=lf, bg="transparent",
with(subset(df, factor == i), hist(x, ....)
dev.off()
}
答案 1 :(得分:4)
在这种情况下,一个合理的选择是使用split
将您的数据框转换为数据框列表,每个数据框包含具有特定因子级别的子集。
split_df <- split(df, df$factor)
正如科林所说,paste
可以被矢量化,所以你只需要调用一次。
lfile <- paste("test_", names(split_df), ".png", sep = "")
将所有绘图代码分组到一个函数中。
draw_and_save_histogram <- function(data, file)
{
png(file)
with(data, hist(x))
dev.off()
}
现在,您可以更轻松地比较普通循环和*apply
函数之间的差异(在本例中为mapply
,因为我们需要两个输入)。
for(i in seq_along(split_df))
{
draw_and_save_histogram(split_df[[i]], lfile[i])
}
mapply(
draw_and_save_histogram,
split_df,
lfile
)
使用lattice
或ggplot2
绘制一个包含多个面板的图表,而不是绘制大量的直方图以保存在不同的文件中。
library(lattice)
histogram(~ x | factor, df)
library(ggplot2)
ggplot(df, aes(x)) + geom_histogram() + facet_wrap(~ factor)