温馨提示:本文翻译自stackoverflow.com,查看原文请点击:r - How to use ggplot2 aes_string() with cut() in a for loop?
ggplot2 r

r - 如何在for循环中将ggplot2 aes_string()与cut()结合使用?

发布于 2020-03-27 16:13:33

我想遍历一些连续的变量来创建ggplots。可以与配合使用aes_string,但是我现在尝试了数千种变体,以包含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)

查看更多

查看更多

提问者
crazysantaclaus
被浏览
70
527 2020-02-01 10:01

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

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)