I have a data frame in R called df:
set.seed(123) # Setting seed for reproducibility
levels <- c('a', 'b', 'c', 'd', 'e')
my_var <- sample(levels, 50, replace = TRUE)
levels2 <- c('a', 'b', 'c', 'd', 'e','f','h')
my_var2 <- sample(levels2, 50, replace = TRUE)
delta <- rnorm(50, mean = 0, sd = 1)
df = tibble(my_var,my_var2,delta);df
# A tibble: 50 × 3
my_var my_var2 delta
<chr> <chr> <dbl>
1 c h 0.304
2 c a 0.448
3 b h 0.0530
4 b b 0.922
5 c d 2.05
6 e h -0.491
7 d d -2.31
8 a f 1.01
9 b f -0.709
10 c c -0.688
# ℹ 40 more rows
I want to plot them with facets like the pcture that I attach but the values of delta column to be sort from worst to best. (i.e. from smaller to bigger) but starting the worst from the bottom and left of each facet and increase to best (bigger) at top right.
How can I achieve this?
df = tibble(my_var,my_var2,delta);df
df%>%
mutate(BandRange = factor(my_var2,levels=levels2)) %>%
ggplot(aes(x = delta, y = (my_var2), color = "black")) +
geom_point(size = 3) +
facet_grid(my_var ~., scales="free") +
labs(y="my_var2") +
geom_vline(xintercept=0) +
theme_bw() +
theme(legend.position = "none", # Remove the legend
axis.text.x = element_text(angle = 0 , hjust = 1), # Rotate x-axis labels
strip.text.y = element_text(size = 8 , angle = 0, vjust = 0.5),
axis.text.y = element_text(size = 7),
strip.text = element_text(size = 14), # Increase facet label size
axis.title = element_text(size = 14), # Increase axis title size
axis.text = element_text(size = 10))+ # Increase axis text size
theme(strip.background = element_rect(color="black", size=1.5, linetype="solid"))+
labs(title = "",x = "")
For simplicity I changed the delta value to be sequence from 1 to 50. I just want to be plotted the delta inside each facet from lower value to the higher value regardless of the my_var2 levels.
levels <- c('a', 'b', 'c', 'd', 'e')
my_var <- sample(levels, 50, replace = TRUE)
levels2 <- c('a', 'b', 'c', 'd', 'e','f','h')
my_var2 <- sample(levels2, 50, replace = TRUE)
delta <- seq(1,50,1);delta
df = tibble(my_var,my_var2,delta)
Okay, I think I've understood what you are trying to do, and worked out a way of doing it. It's slightly hacky, but I think it needs to be, because you're trying to order your y axis differently for each facet, but without using alphabetical order or an ordered factor (because the orders of a factor would be the same for the whole column).
You need to create a new variable for ordering, then edit the variable labels to make it look right:
## Libraries -------------------------------------
library(ggplot2)
library(dplyr)
library(forcats)
library(stringr)
## init data --------------------------------------
set.seed(123) # Setting seed for reproducibility
levels <- c('a', 'b', 'c', 'd', 'e')
my_var <- sample(levels, 50, replace = TRUE)
levels2 <- c('a', 'b', 'c', 'd', 'e','f','h')
my_var2 <- sample(levels2, 50, replace = TRUE)
delta <- rnorm(50, mean = 0, sd = 1)
df <- tibble(my_var,my_var2,delta)
Group the data by the facetting variable, then arrange by the 'arranging' variable (i.e. delta). Then you can prefix the new labels with letters from a-z, so that alphabetical ordering will preserve your desired order:
## Create proxy variable for ordering --------------
df <-
group_by(df, my_var) |>
arrange(delta, .by_group = TRUE) |>
mutate(labels = paste0(letters[1:n()], "/", my_var2))
head(df)
#> # A tibble: 6 × 4
#> # Groups: my_var [1]
#> my_var my_var2 delta labels
#> <chr> <chr> <dbl> <chr>
#> 1 a a -0.600 a/a
#> 2 a f -0.575 b/f
#> 3 a f -0.348 c/f
#> 4 a e -0.0556 d/e
#> 5 a f 0.00576 e/f
#> 6 a h 0.181 f/h
To make it look right, you need to pass a function to the label
argument of scale_y_discrete()
. This function will extract the 'real' label from each of your new labels, so that the alphabetical ordering part is not shown:
## Extract label from proxy variable --------------
ggplot(df, aes(x = delta, y = labels)) +
geom_point(colour = "red") +
# "free_y" lets the y axis move around between facets
facet_wrap(~my_var, dir = "v", ncol = 1, scales = "free_y") +
# Remove the ordering component of each label:
scale_y_discrete(labels = \(x) str_extract(x, "(?<=/)."))
Voila:
Created on 2024-11-07 with reprex v2.1.1