1

how do i correct the span of the y-axis, since the first diagramme has bigger range but the last diagramme has smaller range.

I tried using expand_limit() , but i have to define the limit. what i want is to specify my limit based on the mean value +- 10%

statistic mean max min

Data
structure(list(height = structure(1:21, .Label = c("_150_5_", 
"_150_4_", "01_150_3_", "01_150_2_", "_150_1_", 
"01_130_5_", "01_130_4_", "01_130_3_", "01_130_2_", 
"L01_130_1_", "01_100_5_", "01_100_4_", "01_100_3_", 
"01_100_2_", "01_100_1_", "01_60_5_", "01_60_4_", 
"01_60_3_", "01_60_2_", "01_60_1_", "01_30_5_"
), class = "factor"), max = c(153.502609757564, 153.803890640307, 
154.030628562627, 153.502609757564, 153.577819267489, 133.497584806195, 
133.440753139611, 133.896765965376, 134.068575331457, 133.725396384362, 
102.872441458794, 103.347289523556, 103.279185873129, 101.048462000305, 
102.035263387027, 60.852713866229, 60.8645299271739, 60.9236791302129, 
60.8763505777715, 61.0542129187662, 30.8972231764362), mean = c(152.038047221229, 
151.858031107105, 152.211206935181, 151.759867764584, 150.344389742043, 
131.874101333396, 131.706179220053, 131.043612919162, 132.264362261993, 
130.599623937693, 101.774080628225, 102.110144624754, 102.239940146821, 
100.053415273797, 100.577556727676, 60.299452319695, 60.3004949199648, 
60.3066081777292, 60.3048844335163, 60.3267015589117, 30.347932670538
), min = c(150.120847282062, 148.344689600069, 148.767123457497, 
148.20441093378, 146.06352708525, 129.15217516479, 129.258692422658, 
127.367870428665, 129.418798152331, 127.006616339119, 99.7938010585627, 
100.401130405172, 101.081047766832, 98.2917306757434, 99.1623945349401, 
59.7507299132569, 59.7507299132569, 59.8077330900488, 59.7507299132569, 
59.8191467795698, 29.7732075536612), sd = c(0.384120348675233, 
0.996143559832467, 0.892389162104352, 0.668245088780541, 1.26871400480022, 
0.717796939735463, 0.841062860547558, 1.09283360068465, 0.801961749792679, 
1.40866403449516, 0.370811042540416, 0.387499052903713, 0.273143219592094, 
0.372612511324188, 0.448178158096896, 0.141781338201885, 0.143328065432486, 
0.140326202644008, 0.141854728955873, 0.139981570704421, 0.155319872754675
)), class = "data.frame", row.names = c(NA, -21L))

the code i have tried

    ii=1
 k=0
 plot_list_stat=list()
 par(mfcol = c(5, 1))
 for (i in 1:4 ){
   k=k+1
 plot_list_stat[[ii]]=ggplot(stat.std_w[k:(k+4),],aes(x=height,y=mean,group=1))+
   geom_ribbon(aes(x=height,ymax=max,ymin=min,color="min-max"
   ),alpha=0.6,fill= "skyblue",show.legend=TRUE)+ 
   scale_fill_manual("",values ="skyblue", guide = FALSE)+
   geom_line()+ylab("")+
   geom_point()+
   theme(axis.text.x = element_text(angle = 90))+
   geom_errorbar(aes(ymin=mean-sd, ymax=mean+sd,color="mean±sd"
   ), width=.2,position=position_dodge(0.05))+theme(legend.position = "none")
 print(ii); #plot_list_stat[[ii]]
 ii=ii+1;k=k+4;)

 library("cowplot")
pgrid=plot_grid(plotlist=plot_list_stat,nrow=1)
library(ggpubr)
pgrid=ggarrange(pgrid,common.legend = T)
annotate_figure(pgrid,
                top = text_grob("statistic ", size = 14),
                left = text_grob(" mean",rot = 90))
tjebo
  • 21,977
  • 7
  • 58
  • 94

2 Answers2

1

I'd use facets instead. With this for looping you're kind of making your own life really complicated.

library(tidyverse)

df %>% 
  # makes new variables
  separate(height, into = c("x", "height", "index")) %>%
ggplot(aes(x = index, y = mean, group = 1)) +
  geom_ribbon(aes(x = index, ymax = max, ymin = min, color = "min-max"), alpha = 0.6, fill = "skyblue", show.legend = TRUE) +
  geom_line() +
  geom_point() +
  geom_errorbar(aes(ymin = mean - sd, ymax = mean + sd, color = "mean±sd"), width = .2, position = position_dodge(0.05)) +
  scale_fill_manual(values = "skyblue", guide = FALSE) +
  labs(y = NULL) + # use NULL, not "" !!
  facet_grid(~height) +
  theme(axis.text.x = element_text(angle = 90), legend.position = "none")
#> Warning: Expected 3 pieces. Additional pieces discarded in 21 rows [1, 2, 3, 4,
#> 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...].
#> geom_path: Each group consists of only one observation. Do you need to adjust
#> the group aesthetic?

Created on 2021-03-15 by the reprex package (v1.0.0)

I personally would prefer the same scale in this case, but if you want flexible y scales, use facet_wrap instead

df %>% 
  # makes new variables
  separate(height, into = c("x", "height", "index")) %>%
  ggplot(aes(x = index, y = mean, group = 1)) +
  geom_ribbon(aes(x = index, ymax = max, ymin = min, color = "min-max"), alpha = 0.6, fill = "skyblue", show.legend = TRUE) +
  geom_line() +
  geom_point() +
  geom_errorbar(aes(ymin = mean - sd, ymax = mean + sd, color = "mean±sd"), width = .2, position = position_dodge(0.05)) +
  scale_fill_manual(values = "skyblue", guide = FALSE) +
  labs(y = NULL) +
  facet_wrap(~height, scales = "free_y", nrow = 1) +
  theme(axis.text.x = element_text(angle = 90), legend.position = "none")

tjebo
  • 21,977
  • 7
  • 58
  • 94
  • should i using scale y ? i just want to plot another scale of y-axis, i mean the one with 60 should be thinner than the one with 150. thx for suggesting me with the facet_wrap – Peter_pan_pinter Mar 15 '21 at 17:06
  • @Peter_pan_pinter to set each scale individually, check https://stackoverflow.com/a/51736379/7941188 – tjebo Mar 15 '21 at 17:31
  • @Peter_pan_pinter - I just updated my answer to adjust the each panel separately to +/- 10% of the mean in that panel. I assume this is what you were after? If not, please clarify the calculation used to determine the adjustment to the plot area. – Dan Adams Mar 15 '21 at 18:43
1

By default the plot area will be expanded by a small amount from the extreme values in the data. There are a number of mechanisms for manually overriding this behavior depending on your needs. In generaly they are much harder to implement in faceted plots, but the visual you're after really calls for faceting so below I'm showing a solution with geom_blank() which will work with this example.

library(tidyverse)

# parse text in 'height' variable to be sortable
df2 <- df %>% 
  separate(col = height, into = c("sub_grp", "grp", "order"), remove = F, fill = "left") %>% 
  mutate(grp = fct_rev(factor(as.numeric(grp))),
         order = fct_rev(factor(as.numeric(order)))) 
#> Warning: Expected 3 pieces. Additional pieces discarded in 21 rows [1, 2, 3, 4,
#> 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...].

# set fraction to expand plot by
# these are based on the requested +/- 10% in the question
fract_up <- 1.1
fract_down <- 0.9

# extract table of limits to expand plot by
df3 <- df2 %>% 
  group_by(grp) %>% 
  summarise(grp_mean = mean(mean), grp_order = mean(as.numeric(order))) %>% 
  mutate(grp_top = fract_up * grp_mean, grp_bot = fract_down * grp_mean, .keep = "unused") %>% 
  pivot_longer(-c(grp, grp_order), names_to = "type", names_prefix = "grp_")

# plot it all together
df2 %>% 
  ggplot(aes(x = order, y = mean, group = grp)) +
  geom_ribbon(
    aes(
      ymax = max,
      ymin = min,
      color = "min-max",
      group = grp
    ),
    alpha = 0.6,
    fill = "skyblue"
  ) +
  geom_line() + 
  geom_point() +
  geom_errorbar(
    aes(
      ymin = mean - sd,
      ymax = mean + sd,
      color = "mean±sd"
    ),
    width = .2,
    position = position_dodge(0.05)
  ) + 
  geom_blank(data = df3, aes(x = grp_order, y = value)) +
  facet_wrap(facets = vars(grp),
             scales = "free",
             nrow = 1) +
  scale_x_discrete(NULL, labels = df2$height) +
  ggtitle("Standard statistic") +
  ylab("Mean") +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5), 
        plot.title = element_text(hjust = 0.5))
#> geom_path: Each group consists of only one observation. Do you need to adjust
#> the group aesthetic?

Created on 2021-03-15 by the reprex package (v1.0.0)

Dan Adams
  • 4,971
  • 9
  • 28