1

我正在尝试遍历一些连续变量以创建 ggplots。这适用于aes_string,但我现在已经尝试了 1000 种变体,以包含cut在生成变量箱的调用中。但它要么失败,要么循环不起作用,并且它一直使用相同的变量值aes

在我的实际数据中,我尝试预先计算类似于的breaksfor ,因为每个变量都有不同的范围,但这也没有帮助。cutcut_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)
4

1 回答 1

3

我们可以使用非标准评估:

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)
于 2020-01-31T09:07:36.213 回答