无法在for循环内的ggplot2中使用facet

问题描述

我有一个包含2个因子的数据框,称为dat.avg

> head(dat.avg)
  Metal     site    season   Average      STDV
1    Al     Acre spring 19 4034.7345  222.4645
2    Al     Acre    summer 5860.1790 2940.4691
3    Al Ashqelon    autumn 2148.6943  403.5688
4    Al Ashqelon spring 19 3336.1576  871.4381
5    Al Ashqelon spring 20 2170.9057  589.2840
6    Al Ashqelon    summer  918.3047  413.6208

> str(dat.avg)
'data.frame':   351 obs. of  5 variables:
 $ Metal  : chr  "Al" "Al" "Al" "Al" ...
 $ site   : Factor w/ 7 levels "Acre","Ashqelon",..: 1 1 2 2 2 2 2 3 3 3 ...
 $ season : Factor w/ 5 levels "autumn","spring 19",..: 2 4 1 2 3 4 5 1 3 5 ...
 $ Average: num  4035 5860 2149 3336 2171 ...
 $ STDV   : num  222 2940 404 871 589 ...

我想生成一个循环,该循环将使用ggplot绘制每种金属的条形图,其中X轴按位置分组,并且在每个位置嵌套所有季节(所有金属相同,因此无需更改)。 Y轴为平均值,每种金属的比例不同,因此其“比例=自由”。 我设法分别对每种金属进行处理,但是由于某种原因,无论我尝试了什么,脸都无法使用。这是我的代码,如果有人可以指出我在做什么错,那就太神奇了。

> Metal.vec
 [1] "Al" "As" "Cd" "Co" "Cr" "Cu" "Fe" "Mg" "Mn" "Ni" "Pb" "Se" "V"  "Zn"

for (j in 1:length(Metal.vec)) { 
  temp.dat.avg  <- dat.avg %>%
    filter(site == dat.avg$site,Metal == Metal.vec[j],Average == dat.avg$Average,season == dat.avg$season)
  Metal.bar  <- ggplot(temp.dat.avg,aes(x = site,y = Average,fill = season)) +
  geom_bar(stat='identity',color="black",position=position_dodge())+
  theme_minimal() + 
  #facet_wrap(~ Metal.vec[j])+
  #facet_grid(vars(Metal.vec[j]),scales = "free",space = "free") + 
  geom_errorbar(aes(ymin=Average-STDV,ymax=Average+STDV),width=.2,position=position_dodge(.9)) +
  ggtitle(Metal.vec[j],"Average and SD Concentration")+
  ylab("Average Metal Concentration in dry weight (µg/g)")
  print(Metal.bar + scale_fill_brewer(palette="Spectral"))
}

我在两个方面的代码中都加上了“#”,以便您可以看到 #facet_wrap(〜Metal.vec [j])+ #facet_grid(vars(Metal.vec [j]),scales =“ free”,space =“ free”) 没人为我工作

我的想法是制作这张图:this kind of bar plot

在金属上刻有小面的外观:this kind of faceting

我将不胜感激! 非常感谢!

解决方法

评论通常是正确的。最终,您只需要facet_wrap(〜metal)。

您应该查看dplyr的group_by并进行汇总,然后再进行绘图。使用group_by按地点,季节和金属分组,然后使用摘要创建一个新列,例如GroupAverage,例如:

function showBrand(clicked_id) {
    var brand = document.getElementById(clicked_id+'-box');

    if (brand.style.display == "none") {
      brand.style.display = "flex";
    }
    else {
      brand.style.display = "none";
    }
}

然后,您可以摆脱外部循环,并使用facet_wrap层调用ggplot。

同样,通常,如果您开始对R使用显式循环,则可能效率低下。 ?

祝你好运。

,

如果您使用facet()绘制多个图,则无需使用循环。

我不确定我是否了解你想要的东西。

考虑到您不会发布可复制的代码和数据,我会伪造数据。

library(tidyverse)
set.seed(20201011)

#FAKE DATA
metal <- c("Al","As","Cd","Co")
site <- paste('City',LETTERS[1:5],sep = '_')
season <- c('spring','summer','autumn','winter')

frames <- expand.grid(metal = metal,site = site,season = season)
dat.avg <- frames %>% cbind(Average = runif(nrow(frames),min = 1,max = 10),STDV = runif(nrow(frames),max = 5)) 

dat.avg如下:

> head(dat.avg,5)
  metal   site season  Average     STDV
1    Al City_A spring 9.430763 1.781402
2    As City_A spring 3.924159 2.714745
3    Cd City_A spring 1.598158 2.950350
4    Co City_A spring 7.171125 1.415245
5    Al City_B spring 2.257886 2.482321

首先,我们创建一个基本构图,该构图仅包含metal面。

p1 <- ggplot(dat.avg,aes(x = season,y = Average,fill= site))+ facet_grid(metal ~.)
p1

enter image description here

第二,在p1上添加条形图

p2 <- p1 + geom_bar(position = position_dodge(),stat="identity",color = 'black') 
p2

enter image description here

第三,基于p2添加错误栏。

p3 <- p2 + geom_errorbar(aes(ymin=Average-STDV,ymax=Average+STDV),position = position_dodge(0.9),width = .3) 
p3

enter image description here

第四,如果您想要this kind of faceting之类的theme,请尝试以下操作:

p4 <- p3 + 
     labs(
    title = 'Variation in Metals Conentration along Israeli Mediterranean Coastline,by Season and Site',subtitle  = 'North to South',caption = 'Field Smapling 2019-2020,\n *Outliers omited for better visualization'
     ) +
     theme(
    plot.title = element_text(color = 'Darkblue'),plot.subtitle = element_text(color = 'blue'),plot.caption = element_text(color = 'green',face = 'bold')
      ) + 
     guides(fill = F)
p4

enter image description here

最后,如果您想要像this kind of bar plot这样的配色方案,请尝试以下操作:

p5 <- p4 + scale_fill_manual(values = c('#D7191C','#FDAE61','#FFFFBF','#ABDDA4','#2B83BA'))
p5

enter image description here

希望这些代码可以为您提供帮助。