我想遍历一些连续的变量来创建ggplots。可以与配合使用aes_string
,但是我现在尝试了数千种变体,以包含cut
在生成变量箱的调用中。但是它要么失败,要么循环不起作用,并且aes
始终使用相同的变量值。
在我的实际数据中,由于每个变量具有不同的范围,因此我尝试预先计算类似于的breaks
for ,但这也无济于事。cut
cut_interval(n = 6)
library(tidyverse)
data(diamonds)
diamonds <- head(diamonds, 200)
# select some numeric categories to loop over
categories <- names(diamonds)[c(1,5,6)]
# this works fine in a loop
plot_list <- list()
for (category in categories){
plot_list[[category]] <- ggplot(diamonds, aes(x = x, y = z)) +
geom_point(data = diamonds[diamonds$color == "E", ], aes_string(fill = category), colour = "grey50", pch = 21) +
geom_point(data = diamonds[diamonds$color != "E", ], aes_string(fill = category, colour = "price"), pch = 21)
}
plot_list
# together with cut(), it does not work anymore
cut_plot_list <- list()
for (category in categories){
cut_plot_list[[category]] <- ggplot(diamonds, aes(x = x, y = z)) +
geom_point(data = diamonds[diamonds$color == "E", ], aes_string(fill = cut(category, breaks = c(-Inf, 1, 10, 20, Inf)), colour = "grey50", pch = 21) +
geom_point(data = diamonds[diamonds$color != "E", ], aes_string(fill = cut(category, breaks = c(-Inf, 1, 10, 20, Inf))), colour = "price"), pch = 21)
}
# fails: 'x' must be numeric
# this gives identical plots without fill
cut_plot_list <- list()
for (category in categories){
cut_plot_list[[category]] <- ggplot(diamonds, aes(x = x, y = z)) +
geom_point(data = diamonds[diamonds$color == "E", ], aes(fill = cut(get(category), breaks = c(-Inf, 1, 10, 20, Inf)), colour = "grey50", pch = 21) +
geom_point(data = diamonds[diamonds$color != "E", ], aes(fill = cut(get(category), breaks = c(-Inf, 1, 10, 20, Inf)), colour = price), pch = 21)
}
cut_plot_list
如何将ggplot2中的for循环(或lapply)与变量的动态离散值结合在一起?
编辑:
没有一个变量的for循环,我会这样称呼它:
ggplot(diamonds, aes(x = x, y = z)) +
geom_point(data = diamonds[diamonds$color == "E", ], aes(fill = table), colour = "grey50", pch = 21) +
geom_point(data = diamonds[diamonds$color != "E", ], aes(fill = table , colour = price), pch = 21)
# or with the binned values
ggplot(diamonds, aes(x = x, y = z)) +
geom_point(data = diamonds[diamonds$color == "E", ], aes(fill = cut(table, breaks = c(-Inf, 1, 10, 20, Inf))), colour = "grey50", pch = 21) +
geom_point(data = diamonds[diamonds$color != "E", ], aes(fill = cut(table, breaks = c(-Inf, 1, 10, 20, Inf)) , colour = price), pch = 21)
我们可以使用非标准评估:
library(ggplot2)
apply_fun <- function(category) {
ggplot(diamonds, aes(x = x, y = z)) +
geom_point(data = diamonds[diamonds$color == "E", ],
aes(fill = cut(!!sym(category), breaks = c(-Inf, 1, 10, 20, Inf))),
colour = "grey50", pch = 21) +
geom_point(data = diamonds[diamonds$color != "E", ],
aes(fill = cut(!!sym(category), breaks = c(-Inf, 1, 10, 20, Inf)) ,
colour = price), pch = 21)
}
然后要求每个 categories
plot_list <- lapply(categories, apply_fun)
要将数据分成一定n
间隔,我们可以做
apply_fun <- function(category, n) {
breaks = seq(min(diamonds[[category]]), max(diamonds[[category]]), length.out = n)
ggplot(diamonds, aes(x = x, y = z)) +
geom_point(data = diamonds[diamonds$color == "E", ],
aes(fill = cut(!!sym(category), breaks = breaks)),
colour = "grey50", pch = 21) +
geom_point(data = diamonds[diamonds$color != "E", ],
aes(fill = cut(!!sym(category), breaks = breaks) ,
colour = price), pch = 21)
}
应用功能
plot_list <- lapply(categories, apply_fun, n = 6)
效果很好,谢谢!有没有办法将对象也提供为
cut(breaks=)
参数的输入?我尝试fill = cut_interval(!!sym(category), n = 6))
在通话中尝试为每个类别设置合适的垃圾箱,但这将使我总共有12个垃圾箱,每个垃圾箱分别为color == "E"
和的6个垃圾箱color != "E"
。我会在ggplot调用之前定义中断,但由于它们不是中断,因此我无法使用!!sym()
@crazysantaclaus我已经更新了答案。那是你要的吗?
太完美了!您可以向我解释一下,为什么
breaks
变量不使用!!sym
而category
不起作用?我也会略微修改您的代码,因为我忘记使用pch
此处可以实际显示的代码fill
@crazysantaclaus
sym
仅用于列,而不用于诸如的值breaks
。