代码说明:我有一个数据框dfs
,其中我存储了其他数据框的名称(df1
和df2
)。 df1
和df2
都包含两个发行版的数据。
我想制作两个单独的(双)条形图;一个用于df1
和df2
。每个条形图比较两个分布。要使用的小节的颜色列在dfs
中(例如df1
我要使用red1
和red4
)。
我尝试通过循环数据框dfs
来做到这一点(这只是一个说明性示例,实际上我有比df1
和df2
更多的数据框)并创建每个数据框'df1'和'df2'的条形图对象。
我使用scale_fill_manual(values = barColours)
为条形指定颜色。不幸的是,当我最后绘制数字(df1_plot
和df2_plot
)时,会使用最后一次迭代的颜色(换句话说,df2_plot
的颜色也用于{ {1}})。
有没有办法确保df1_plot
使用预期的颜色而不会丢失df1_plot
循环?
for
答案 0 :(得分:2)
在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]]
答案 1 :(得分:1)
这是因为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]]