Peter_pan_pinter
Peter_pan_pinter

Reputation: 15

make the width scale of y axis proper size in R

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))

Upvotes: 1

Views: 351

Answers (2)

Dan Adams
Dan Adams

Reputation: 5204

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)

Upvotes: 1

tjebo
tjebo

Reputation: 23737

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")

Upvotes: 1

Related Questions