代码说明:我有一个数据框dfs
,其中存储了其他数据框(df1
和df2
)的名称。df1
和df2
都包含两个分布的数据。
我想制作两个单独的(双)条形图;一个用于df1
和df2
。每个条形图比较两个分布。要使用的条形的颜色以dfs
列出(例如,对于我想使用red1
和red4
df1
)。
我尝试通过循环遍历数据框dfs
(这只是一个说明性示例,实际上我拥有的数据框比df1
和df2
多得多)并为每个数据框"df1"和"df2"创建一个条形图对象。
我使用scale_fill_manual(values = barColours)
为条形分配颜色。不幸的是,当我最后绘制图形时(df1_plot
和df2_plot
),使用了上次迭代的颜色(换句话说,df2_plot
的颜色也用于df1_plot
)。
有没有办法确保df1_plot
使用预期的颜色而不会丢失for
循环?
library(ggplot2)
col1 = c("red1", "green1")
col2 = c("red4", "green4")
dfs = data.frame(df = c("df1", "df2"), col1, col2 , stringsAsFactors = FALSE)
category_type1 = rep(c("A", "B"), each = 3)
category1 = rep(c(1, 2, 3), 2)
weight1 = c(5, 8, 9, 6, 4, 7)
df1 = data.frame(category_type = category_type1, category = category1, weight = weight1, stringsAsFactors = FALSE)
category_type2 = rep(c("A", "B"), each = 3)
category2 = rep(c(1, 2, 3), 2)
weight2 = c(10, 2, 1, 1, 5 , 7)
df2 = data.frame(category_type = category_type2, category = category2, weight = weight2, stringsAsFactors = FALSE)
for (i in 1:2) {
assign("data", eval(as.name(dfs[i, "df"])))
barColours = c(dfs[i, "col1"], dfs[i, "col2"])
distribution = ggplot(data, aes(x = category, y = weight, fill = category_type)) +
geom_bar(stat = "identity", position = "dodge") +
scale_fill_manual(values = barColours)
assign(paste0(dfs[i, "df"], "_plot"), distribution)
}
df1_plot
df2_plot
在 R 中执行此操作的更惯用的方法是使用列表:
- 创建输入数据框列表
- 使用
lapply()
创建包含绘图的新列表:
请注意,这根本不使用assign()
- 一般来说,如果你想使用assign()
,这表明几乎可以肯定有一种更简单的方法可以做到这一点。
试试这个:
input_data = list(df1, df2)
df_plot <- lapply(1:2, function(i){
dat <- input_data[[i]]
barColours = c(dfs[i, "col1"], dfs[i, "col2"])
ggplot(dat, aes(x = category, y = weight, fill = category_type)) +
geom_bar(stat = "identity", position = "dodge") +
scale_fill_manual(values = barColours)
})
df_plot[[1]]
df_plot[[2]]
这是因为ggplot
对象仅在打印或构建时进行评估,而不是在构造时进行评估。由于打印打印时i
已更改,因此它将使用新值。处理此问题的一种方法是显式构建绘图:
plots <- list()
for (i in 1:2) {
df = eval(as.name(dfs[i, "df"]))
barColours = c(dfs[i, "col1"], dfs[i, "col2"])
distribution = ggplot(df, aes(x = category, y = weight, fill = category_type)) +
geom_bar(stat = "identity", position = "dodge") +
scale_fill_manual(values = barColours)
plots[[i]] = ggplot_build(distribution)
}
plots[[1]]$plot
请注意,我已经删除了您对assign
的使用,因为我更喜欢将内容存储在列表中。
我的首选方法是不使用循环,而是使用带有列表的函数:
f <- function(df, barColours) {
ggplot(df, aes(x = category, y = weight, fill = category_type)) +
geom_bar(stat = "identity", position = "dodge") +
scale_fill_manual(values = barColours)
}
plots <- Map(f, list(df1, df2), list(c('red1', 'red4'), c('green1', 'green4')))
plots[[1]]