【问题标题】:Loop to plot boxplot with ggplot循环使用 ggplot 绘制箱线图
【发布时间】:2020-11-02 23:53:43
【问题描述】:

我正在使用钻石 df,

我想按类别为每个数字列绘制箱线图, 在这种情况下,类别将由“cut”列定义。

我正在使用 for 循环来完成这项任务,

这是我正在使用的代码:


##################################################################################
#                              Data                                              #
#                                                                                #
##################################################################################

data("diamonds")
basePlot <- diamonds[ names(diamonds)[!names(diamonds) %in% c("color", "clarity")] ]

##################################################################################

## set Plot view to 4 boxplots ##
par(mfrow = c(2,2))

## for-loop to boxplot all numerical columns ##

for (i in 1:(ncol(basePlot)-1)){
  print(ggplot(basePlot, aes(as.factor(cut), 
  basePlot[c(i)],color=as.factor(cut)))
        + geom_boxplot(outlier.colour="black",outlier.shape=16,outlier.size=1,notch=FALSE)
        + xlab("Diamond Cut")
        + ylab(colnames(basePlot)[i])
  )
}


控制台输出:

Don't know how to automatically pick scale for object of type data.frame. Defaulting to continuous.
Error in is.finite(x) : default method not implemented for type 'list'

还有其他方法可以完成这项任务吗?

【问题讨论】:

  • 由于我们没有您的数据,您是否介意根据mtcarsdiamonds 等公共数据集重新提出您的问题?另外,您是否考虑过使用 facets 或其他一些分组机制来替代生成多个图?
  • 嘿@r2evans,已经编辑,所以它可以是一个可重复的例子;没有使用构面

标签: r dataframe for-loop ggplot2 boxplot


【解决方案1】:

我建议facets,而不是多个图。不过,要做到这一点,我们需要将数据从“宽”格式转换为“长”格式,tidyverse 中的规范方式是tidyr::pivot_longer

> basePlot
# A tibble: 53,940 x 8
   carat cut       depth table price     x     y     z
   <dbl> <ord>     <dbl> <dbl> <int> <dbl> <dbl> <dbl>
 1 0.23  Ideal      61.5    55   326  3.95  3.98  2.43
 2 0.21  Premium    59.8    61   326  3.89  3.84  2.31
 3 0.23  Good       56.9    65   327  4.05  4.07  2.31
 4 0.290 Premium    62.4    58   334  4.2   4.23  2.63
 5 0.31  Good       63.3    58   335  4.34  4.35  2.75
 6 0.24  Very Good  62.8    57   336  3.94  3.96  2.48
 7 0.24  Very Good  62.3    57   336  3.95  3.98  2.47
 8 0.26  Very Good  61.9    55   337  4.07  4.11  2.53
 9 0.22  Fair       65.1    61   337  3.87  3.78  2.49
10 0.23  Very Good  59.4    61   338  4     4.05  2.39
# ... with 53,930 more rows
> pivot_longer(basePlot, -cut, names_to="var", values_to="val")
# A tibble: 377,580 x 3
   cut     var      val
   <ord>   <chr>  <dbl>
 1 Ideal   carat   0.23
 2 Ideal   depth  61.5 
 3 Ideal   table  55   
 4 Ideal   price 326   
 5 Ideal   x       3.95
 6 Ideal   y       3.98
 7 Ideal   z       2.43
 8 Premium carat   0.21
 9 Premium depth  59.8 
10 Premium table  61   
# ... with 377,570 more rows

有了这个,我们只需要告诉ggplot2 担心val 的值和var 的x 轴。

library(ggplot2)
library(tidyr) # pivot_longer

ggplot(pivot_longer(basePlot, -cut, names_to="var", values_to="val"),
       aes(cut, val, color=cut)) +
  geom_boxplot(outlier.colour="black", outlier.shape=16, outlier.size=1, notch=FALSE) +
  xlab("Diamond Cut") +
  facet_wrap(~var, nrow=2, scales="free") +
  scale_x_discrete(guide=guide_axis(n.dodge=2))

在 x 轴和图例中都有cut 的原因是color= 将添加图例。由于它是多余的,我们可以删除颜色美学(这也会删除图例),或者我们可以直接隐藏图例(通过添加 + scale_color_discrete(guide=FALSE))。

分面有两种方式:facet_wrapfacet_grid。后者针对多个变量(x 上的一个方面变量,y 上的一个方面变量)和许多其他配置进行了很好的调整。当然,您可以只使用一个变量 facet_grid(类似于 facet_wrap(nrow=1)ncol=1),但它们之间存在一些样式区别。

【讨论】:

  • 这很棒,但是我如何通过 Plot 将视图调整为只有 2 个“var”(例如一个视图中的克拉和价格)?在原始数据集中,我有 82 列...
  • 对于“这么多”的看法,限制为basePlot[basePlot$cut %in% c("Fair","Good"),]
  • 是否可以使用那种过滤器,但对于克拉、深度、价格等...可能在facet_wrap 内?
  • 你的意思是像pivot_longer(...) %&gt;% filter(var %in% c("caret", "depth", "price")) %&gt;% ggplot(...) + geom_boxplot(...) + facet_wrap(~var, ...)这样的吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-04
相关资源
最近更新 更多