Free axis along particular facets in facet_grid ggplot - r

I am trying to do 2 things:
First and most important is to somehow get the y axis to vary by the outcome_type2 variable, since they all have fairly different ranges. So the "C" have their own axis range, the "Z" have their own axis range, and the "SS" have their own axis range.
Then the secondary thing would be to somehow adjust the spacing of columns, so that there's a bit of space by those same groups--the 3 "C" columns would be close together, with a bit of extra white space between them and the "Z", then same between "Z" and "SS". Just to differentiate a little more between those three groups.
I tried tinkering with faceting on outcome_type2 instead of outcome_type but to no avail.
This is current base code, which technically works fine, but as you'll see, having them all use the same Y axis really swamps the "Z" and "SS" panels.
ggplot(dtest, aes(x = var2, y = avg2, fill = var2)) +
geom_bar(stat = "identity",
width = 1) +
facet_grid(wave ~ forcats::fct_relevel(outcome_type, "CT", "CI", "CE", "FZ", "MZ", "PSS", "CSS"),
scales = "free_y",
space = "free_y") +
theme_minimal() +
theme(legend.position = "none")
dtest <- structure(list(outcome_type = c("CT", "CT", "CT", "CI", "CI",
"CI", "CE", "CE", "CE", "FZ", "FZ", "MZ", "MZ", "PSS", "PSS",
"CSS", "CSS", "CT", "CT", "CT", "CI", "CI", "CI", "CE", "CE",
"CE", "FZ", "FZ", "MZ", "MZ", "PSS", "PSS", "CSS", "CSS"), wave = c("Wave 1",
"Wave 2", "Wave 3", "Wave 1", "Wave 2", "Wave 3", "Wave 1", "Wave 2",
"Wave 3", "Wave 2", "Wave 3", "Wave 2", "Wave 3", "Wave 1", "Wave 3",
"Wave 1", "Wave 3", "Wave 1", "Wave 2", "Wave 3", "Wave 1", "Wave 2",
"Wave 3", "Wave 1", "Wave 2", "Wave 3", "Wave 2", "Wave 3", "Wave 2",
"Wave 3", "Wave 1", "Wave 3", "Wave 1", "Wave 3"), var2 = c("Skipped",
"Skipped", "Skipped", "Skipped", "Skipped", "Skipped", "Skipped",
"Skipped", "Skipped", "Skipped", "Skipped", "Skipped", "Skipped",
"Skipped", "Skipped", "Skipped", "Skipped", "Attended", "Attended",
"Attended", "Attended", "Attended", "Attended", "Attended", "Attended",
"Attended", "Attended", "Attended", "Attended", "Attended", "Attended",
"Attended", "Attended", "Attended"), avg2 = c(30.21, 20.88, 25.43,
7.68, 8.26, 7.89, 11.15, 8, 5.99, 1.64, 0.43, 0.6, 0.77, 0.01,
-0.09, -0.2, -0.01, 24.01, 19.98, 29.04, 9.82, 12.41, 12.99,
14.35, 11.01, 10, 2.36, 2.3, 1.51, 0.91, -0.23, -0.35, -0.17,
-0.14), outcome_type2 = c("C", "C", "C", "C", "C", "C", "C",
"C", "C", "Z", "Z", "Z", "Z", "SS", "SS", "SS", "SS", "C", "C",
"C", "C", "C", "C", "C", "C", "C", "Z", "Z", "Z", "Z", "SS",
"SS", "SS", "SS")), class = c("spec_tbl_df", "tbl_df", "tbl",
"data.frame"), row.names = c(NA, -34L), spec = structure(list(
cols = list(outcome_type = structure(list(), class = c("collector_character",
"collector")), wave = structure(list(), class = c("collector_character",
"collector")), var2 = structure(list(), class = c("collector_character",
"collector")), avg2 = structure(list(), class = c("collector_double",
"collector")), outcome_type2 = structure(list(), class = c("collector_character",
"collector"))), default = structure(list(), class = c("collector_guess",
"collector")), skip = 1L), class = "col_spec"))

One option would be to create separate plots for each group of panels and glue them together using patchwork. Doing so you get "free" scale for each group of panels automatically and also have one (and only one) axis for each panel group.
To this end first add a group column to your data which could be used to split your dataset by facet panel group. Additionally, for convenience I use a plotting function which also removes the y axis strip texts for the first two groups of panels and as an important step completes each dataset so that all combinations of wave, outcome_type and var2 are present in each sub-dataset.
library(ggplot2)
library(patchwork)
library(magrittr)
dtest$group <- dplyr::case_when(
grepl("SS$", dtest$outcome_type) ~ "SS",
grepl("Z$", dtest$outcome_type) ~ "Z",
TRUE ~ "C"
)
dtest$group <- factor(dtest$group, c("C", "Z", "SS"))
plot_fun <- function(.data) {
remove_facet <- if (unique(.data$group) %in% c("C", "Z")) {
theme(strip.text.y = element_blank())
}
.data$outcome_type <- forcats::fct_relevel(
.data$outcome_type,
"CT", "CI", "CE", "FZ", "MZ", "PSS", "CSS"
)
.data |>
tidyr::complete(outcome_type, wave = unique(dtest$wave), var2) %>%
ggplot(aes(x = var2, y = avg2, fill = var2)) +
geom_bar(
stat = "identity",
width = 1
) +
facet_grid(wave ~ outcome_type) +
theme_minimal() +
remove_facet
}
dtest_split <- split(dtest, dtest$group)
lapply(dtest_split, plot_fun) %>%
wrap_plots() +
plot_layout(widths = c(3, 2, 2), guides = "collect") &
labs(x = NULL, y = NULL, fill = NULL) &
theme(axis.text.x = element_blank())
#> Warning: 4 unknown levels in `f`: FZ, MZ, PSS, and CSS
#> Warning: 5 unknown levels in `f`: CT, CI, CE, PSS, and CSS
#> Warning: 5 unknown levels in `f`: CT, CI, CE, FZ, and MZ
#> Warning: Removed 4 rows containing missing values (`position_stack()`).
#> Removed 4 rows containing missing values (`position_stack()`).

Here is a solution where we first identify those avg2 < 5, then make a list of two data frames and plot for each data frame the corresponding plot:
library(tidyverse)
require(gridExtra)
my_list <- dtest %>%
pivot_longer(c(contains("type"))) %>%
mutate(value = fct_relevel(value, "CT", "CI", "CE", "FZ", "MZ", "PSS", "CSS")) %>%
arrange(value) %>%
mutate(x = ifelse(avg2 <5, 1, 0)) %>%
group_split(x)
plot1 <- ggplot(my_list[[1]], aes(x = var2, y = avg2, fill = var2))+
geom_col()+
facet_grid(wave ~ value) +
theme_minimal() +
theme(legend.position = "none",
strip.text.y = element_blank()
)
plot2 <- ggplot(my_list[[2]], aes(x = var2, y = avg2, fill = var2))+
geom_col()+
facet_grid(wave ~ value)+
theme_minimal() +
theme(legend.position = "none")+
labs(y="")
grid.arrange(plot1, plot2, ncol=2)

Related

Is there a way to change legend to show increasing and decreasing colors for waterfall plot using Plotly (r)?

I've plotted a waterfall chart/plot using plotly. I'm trying to change the legend so that it displays the increasing/decreasing colors (red/green) that I've set. Does anyone know how I would go about doing this? I'm try display only one legend for the entire figure rather than one legend for each subplot. Currently, what displays is the trace with a red and green box (as I've indicated in the picture).
Here is the data:
structure(list(Date = structure(c(1569888000, 1572566400, 1575158400,
1577836800, 1580515200, 1583020800, 1585699200, 1588291200, 1590969600,
1569888000, 1572566400, 1575158400, 1577836800, 1580515200, 1583020800,
1585699200, 1588291200, 1590969600, 1569888000, 1572566400, 1575158400,
1577836800, 1580515200, 1583020800, 1585699200, 1588291200, 1590969600
), class = c("POSIXct", "POSIXt"), tzone = "UTC"), Percent_change = c(-45,
-50, -25, -30, -40, -35, -1, -5, -25, 30, 45, 50, -30, -40, -35,
-1, -5, -25, 50, -45, -30, -15, -20, -35, -1, -5, -25), Toys = c("Toy 1",
"Toy 1", "Toy 1", "Toy 1", "Toy 1", "Toy 1", "Toy 1", "Toy 1",
"Toy 1", "Toy 2", "Toy 2", "Toy 2", "Toy 2", "Toy 2", "Toy 2",
"Toy 2", "Toy 2", "Toy 2", "Toy 3", "Toy 3", "Toy 3", "Toy 3",
"Toy 3", "Toy 3", "Toy 3", "Toy 3", "Toy 3")), class = c("tbl_df",
"tbl", "data.frame"), row.names = c(NA, -27L))
Here is the code:
percent <- function(x, digits = 2, format = "f", ...) {
paste0(formatC(x, format = format, digits = digits, ...), "%")
}
my_plot <- . %>%
plot_ly(x = ~Date, y = ~Percent_change, type = "waterfall",
hoverinfo = "text",
hovertext = ~paste("Date :", Date,
"<br> % Change:", percent(Percent_change)),
increasing = list(marker = list(color = "red")),
decreasing = list(marker = list(color = "green")),
totals = list(marker = list(color = "blue")),
textposition = "outside", legendgroup = "trace 1") %>%
add_annotations(
text = ~unique(Toys),
x = 0.5,
y = 1,
yref = "paper",
xref = "paper",
xanchor = "middle",
yanchor = "top",
showarrow = FALSE,
font = list(size = 15),
yshift = 10
) %>%
layout(yaxis = list(title = "% Change",
ticksuffix = "%"),
xaxis = list(title = c("Date")),
showlegend =T)
example_data %>%
dplyr::filter(!is.na(Date)) %>%
group_by(Toys) %>%
distinct() %>%
do(p = my_plot(.)) %>%
subplot(nrows = 3, shareX = FALSE, titleY= TRUE, titleX= FALSE)
I would like the legend to specifically look like this with the title "Trend" above:
We can create two initial traces representing the two legend items.
After that we need to assign all increasing and decreasing traces into the legendgroups introduced with the initial traces and hide their legend items:
library(plotly)
library(dplyr)
library(data.table)
example_data <- structure(list( Date = structure(c(1569888000, 1572566400,
1575158400, 1577836800, 1580515200, 1583020800, 1585699200, 1588291200,
1590969600, 1569888000, 1572566400, 1575158400, 1577836800, 1580515200,
1583020800, 1585699200, 1588291200, 1590969600, 1569888000, 1572566400,
1575158400, 1577836800, 1580515200, 1583020800, 1585699200, 1588291200,
1590969600), class = c("POSIXct", "POSIXt"), tzone = "UTC"), Percent_change =
c(-45, -50, -25, -30, -40, -35, -1, -5, -25, 30, 45, 50, -30, -40, -35, -1,
-5, -25, 50, -45, -30, -15, -20, -35, -1, -5, -25), Toys = c("Toy 1", "Toy 1",
"Toy 1", "Toy 1", "Toy 1", "Toy 1", "Toy 1", "Toy 1", "Toy 1", "Toy 2", "Toy 2",
"Toy 2", "Toy 2", "Toy 2", "Toy 2", "Toy 2", "Toy 2", "Toy 2", "Toy 3",
"Toy 3", "Toy 3", "Toy 3", "Toy 3", "Toy 3", "Toy 3", "Toy 3", "Toy 3")),
class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -27L))
percent <- function(x, digits = 2, format = "f", ...) {
paste0(formatC(x, format = format, digits = digits, ...), "%")
}
my_plot <- . %>%
plot_ly(
x = ~ Date[1],
y = 0,
type = "bar",
name = "increasing",
color = I("darkgreen"),
legendgroup = "increasing",
showlegend = ~ all(showlegend)
) %>%
add_trace(
x = ~ Date[1],
y = 0,
type = "bar",
name = "decreasing",
color = I("red"),
legendgroup = "decreasing",
showlegend = ~ all(showlegend)
) %>%
add_trace(
x = ~ Date,
y = ~ Percent_change,
type = "waterfall",
# split = ~ legendgroup,
hoverinfo = "text",
hovertext = ~ paste("Date :", Date, "<br> % Change:", percent(Percent_change)),
increasing = list(marker = list(color = "red")),
decreasing = list(marker = list(color = "green")),
totals = list(marker = list(color = "blue")),
textposition = "outside",
legendgroup = ~ legendgroup,
showlegend = FALSE
) %>%
add_annotations(
text = ~ unique(Toys),
x = 0.5,
y = 1,
yref = "paper",
xref = "paper",
xanchor = "middle",
yanchor = "top",
showarrow = FALSE,
font = list(size = 15),
yshift = 10
) %>%
layout(yaxis = list(title = "% Change", ticksuffix = "%"),
xaxis = list(title = c("Date")),
legend = list(
itemclick = FALSE,
itemdoubleclick = FALSE,
groupclick = FALSE
))
example_data %>%
dplyr::filter(!is.na(Date)) %>%
mutate(legendgroup = case_when(
Percent_change >= 0 ~ "increasing",
Percent_change < 0 ~ "decreasing",
)) %>%
mutate(showlegend = data.table::rleid(Toys, legendgroup) %in% c(1, 2)) %>%
group_by(Toys) %>%
distinct() %>%
do(p = my_plot(.)) %>%
subplot(
nrows = 3,
shareX = FALSE,
titleY = TRUE,
titleX = FALSE
)
PS: if you prefer to display your waterfall using separate traces for the increasing and decreasing parts use split = ~ legendgroup in the add_trace call. Furthermore you'll need to set itemclick etc. back to TRUE in the layout call for an interactive legend.
You can edit the legend name in R and use javascript to edit the legend colors
Edit: I'll leave this here as it is a different approach which is sometimes useful, but I think the answer by #ismirsehregal - which doesn't involve hacking the object created by plotly.js - is better.
Steps:
Re-define your my_plot() function so that it names the first trace "decreasing" and the second one "increasing".
Append some javascript to manually change the legend colors.
Call the function, hiding the third legend, and appending the javascript
1. Redefine the function
This is the same as your function except it maps the first two groups to "increasing" or "decreasing".
my_plot <- function(x,
group_name,
groups_to_show_legend = c(
"Toy 1" = "decreasing", "Toy 2" = "increasing"
)) {
x %>%
plot_ly(
x = ~Date, y = ~Percent_change, type = "waterfall",
hoverinfo = "text",
hovertext = ~ paste(
"Date :", Date,
"<br> % Change:", percent(Percent_change)
),
increasing = list(marker = list(color = "red")),
decreasing = list(marker = list(color = "green")),
totals = list(marker = list(color = "blue")),
textposition = "outside",
legendgroup = "trace 1",
name = groups_to_show_legend[group_name]
) %>%
add_annotations(
text = ~ unique(Toys),
x = 0.5,
y = 1,
yref = "paper",
xref = "paper",
xanchor = "middle",
yanchor = "top",
showarrow = FALSE,
font = list(size = 15),
yshift = 10
) %>%
layout(
yaxis = list(
title = "% Change",
ticksuffix = "%"
),
xaxis = list(title = c("Date")),
showlegend = TRUE
)
}
2. Append some javascript
We can define some a javascript string in R which we feed to the htmlwidget created by plotly. This makes the "decreasing" symbol red and the "increasing" symbol green.
js_text <- htmltools::HTML('
let legend = document.querySelector(\'.scrollbox\');\n
let symbols = legend.getElementsByClassName("legendsymbols");\n
const re = new RegExp("fill: rgb.*?;", "ig");\n
symbols[0].innerHTML = symbols[0].innerHTML.replaceAll(re, "fill: rgb(255, 0, 0);");\n
symbols[1].innerHTML = symbols[1].innerHTML.replaceAll(re, "fill: rgb(0, 128, 0);");\n
')
3. Call the function, hiding the third legend, and appending the javascript
I've replaced do(), which is deprecated, with split() followed by purrr::imap(). This also allows us to supply the group names to the function:
example_data |>
dplyr::filter(!is.na(Date)) |>
group_by(Toys) |>
distinct() |>
split(~Toys) |>
purrr::imap(my_plot) |>
subplot(
nrows = 3,
shareX = FALSE,
titleY = TRUE,
titleX = FALSE
) |>
style(showlegend = FALSE, traces = 3) |>
htmlwidgets::prependContent(
htmlwidgets::onStaticRenderComplete(js_text)
)
We use htmlwidgets::prependContent() to attach this code to the plotly object, and htmlwidgets::onStaticRenderComplete() to ensure that it runs once the object is loaded.
You could use style to remove multiple traces. This creates one legend for your graph like this:
library(plotly)
library(dplyr)
my_plot <- . %>%
plot_ly(x = ~Date, y = ~Percent_change, type = "waterfall",
hoverinfo = "text",
hovertext = ~paste("Date :", Date,
"<br> % Change:", percent(Percent_change)),
increasing = list(marker = list(color = "red")),
decreasing = list(marker = list(color = "green")),
totals = list(marker = list(color = "blue")),
textposition = "outside", legendgroup = "trace 1") %>%
add_annotations(
text = ~unique(Toys),
x = 0.5,
y = 1,
yref = "paper",
xref = "paper",
xanchor = "middle",
yanchor = "top",
showarrow = FALSE,
font = list(size = 15),
yshift = 10
) %>%
layout(yaxis = list(title = "% Change",
ticksuffix = "%"),
xaxis = list(title = c("Date")),
showlegend = TRUE)
example_data %>%
dplyr::filter(!is.na(Date)) %>%
group_by(Toys) %>%
distinct() %>%
do(p = my_plot(.)) %>%
subplot(nrows = 3, shareX = FALSE, titleY= TRUE, titleX= FALSE) %>%
style(showlegend = FALSE, traces = c(1,2))
Created on 2023-02-08 with reprex v2.0.2

ggplot by group with filter()

I have big dataset with the following format:
structure(list(LOCATION = c("CAN", "CAN", "CAN", "CAN", "CAN",
"CAN", "CAN", "CAN", "CAN", "CAN"), Country = c("Canada", "Canada",
"Canada", "Canada", "Canada", "Canada", "Canada", "Canada", "Canada",
"Canada"), SUBJECT = c("ULABUL99", "ULABUL99", "ULABUL99", "ULABUL99",
"ULABUL99", "ULABUL99", "ULABUL99", "ULABUL99", "ULABUL99", "ULABUL99"
), Subject = c("Unit Labour Cost", "Unit Labour Cost", "Unit Labour Cost",
"Unit Labour Cost", "Unit Labour Cost", "Unit Labour Cost", "Unit Labour Cost",
"Unit Labour Cost", "Unit Labour Cost", "Unit Labour Cost"),
SECTOR = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), Sector = c("Total Economy",
"Total Economy", "Total Economy", "Total Economy", "Total Economy",
"Total Economy", "Total Economy", "Total Economy", "Total Economy",
"Total Economy"), MEASURE = c("ST", "ST", "ST", "ST", "ST",
"ST", "ST", "ST", "ST", "ST"), Measure = c("Level, ratio or national currency",
"Level, ratio or national currency", "Level, ratio or national currency",
"Level, ratio or national currency", "Level, ratio or national currency",
"Level, ratio or national currency", "Level, ratio or national currency",
"Level, ratio or national currency", "Level, ratio or national currency",
"Level, ratio or national currency"), FREQUENCY = c("A",
"A", "A", "A", "A", "A", "A", "A", "A", "A"), Frequency = c("Annual",
"Annual", "Annual", "Annual", "Annual", "Annual", "Annual",
"Annual", "Annual", "Annual"), TIME = 1970:1979, Time = 1970:1979,
Value = c(0.1304592, 0.1357066, 0.1430287, 0.1521136, 0.1752398,
0.2018611, 0.2193767, 0.2347496, 0.2470616, 0.2663881), Flag.Codes = c("E",
"E", "E", "E", "E", "E", "E", "E", "E", "E"), Flags = c("Estimated value",
"Estimated value", "Estimated value", "Estimated value",
"Estimated value", "Estimated value", "Estimated value",
"Estimated value", "Estimated value", "Estimated value")), row.names = c(NA,
10L), class = "data.frame")
And I want to draw time plot like the following (for each sector group in a particular country's particular subject, in this case, Germany's Labour Income Share)
I tried to code as follows:
library(ggplot2)
library(tidyr)
df <- read.csv("/Users/ulc.csv", header = TRUE)
fsector = factor(df$SECTOR)
df %>%
filter(df$MEASURE =="ST",
df$SUBJECT == "ULAIRU99",
df$LOCATION == "DEU") %>%
ggplot(aes(x = df$year, y = df$value, color = fsector, linetype = fsector)) +
scale_color_manual(labels=c("Sec 1","Sec 2", "Sec 3", "Sec 4", "Sec 5", "Sec 6", "Sec 7", "Sec 8"), values = 1:8) +
scale_linetype_manual(labels=c("Sec 1","Sec 2", "Sec 3", "Sec 4", "Sec 5", "Sec 6", "Sec 7", "Sec 8"), values = 1:8) +
theme(legend.position = c(0.8, 0.3), legend.title = element_blank()) +
ylab("LIS of Germany by sector") + xlab("year")
But the result does not show any plots and seems like a lot of elements are missing in my code. Maybe should I add geom_line() for each sector? But there seems much simpler way. Any help would be appreciated.
You can try the following code -
library(dplyr)
library(ggplot2)
df %>%
filter(MEASURE =="ST",SUBJECT == "ULAIRU99",LOCATION == "DEU") %>%
mutate(SECTOR = factor(SECTOR)) %>%
ggplot(aes(x = TIME, y = Value, color = SECTOR, linetype = SECTOR)) +
geom_line() +
scale_color_manual(labels=c("Sec 1","Sec 2", "Sec 3", "Sec 4", "Sec 5", "Sec 6", "Sec 7", "Sec 8"), values = 1:8) +
scale_linetype_manual(labels=c("Sec 1","Sec 2", "Sec 3", "Sec 4", "Sec 5", "Sec 6", "Sec 7", "Sec 8"), values = 1:8) +
theme(legend.position = c(0.8, 0.3), legend.title = element_blank()) +
ylab("LIS of Germany by sector") + xlab("year")

How to align geom_line and geom_point when points are dodged by a variable and lines by another?

Sample dataset:
df <- structure(list(event = c("Alpha", "Alpha", "Alpha", "Alpha",
"Alpha", "Alpha", "Alpha", "Alpha", "Beta", "Beta", "Beta", "Beta",
"Beta", "Beta", "Beta", "Beta"), ID = c("AV", "AV", "AV", "AV",
"BD", "BD", "BD", "BD", "PH", "PH", "PH", "PH", "TC", "TC", "TC",
"TC"), Split_Q = c("Q1", "Q2", "Q3", "Q4", "Q1", "Q2", "Q3",
"Q4", "Q1", "Q2", "Q3", "Q4", "Q1", "Q2", "Q3", "Q4"), Time = c(82.2,
87, 87.1, 87.2, 85.8, 86.6, 86.8, 86, 91.2, 92.2, 92.7, 90.4,
92.7, 92.9, 92.6, 91.8)), row.names = c(NA, 16L), class = "data.frame")
I have two groups Alpha and Beta, which have an indeterminate amount of observations in my full dataset over four measurements (Q1-Q4). I want to clearly delineate the groups on each side of the four measurements:
plot <- df %>% ggplot(aes(Split_Q, Time, colour = event)) +
geom_point(position = position_dodge(0.5))
Looks okay so far, but when I add a geom_line with the ID variable identifying each observation, and the same position_dodge value, they don't align.
plot + geom_line(aes(group = ID), position = position_dodge(0.5))
Not sure what the procedure is to align them, any advice? Thanks
First add a bit of offset:
library(tidyverse)
df <- df %>%
mutate(Quarter = as.numeric(str_extract(Split_Q, "[:digit:]")),
Quarter = case_when(event == "Alpha" ~ Quarter - 0.1,
event == "Beta" ~ Quarter + 0.1))
Plot and specify labels:
df %>% ggplot(aes(
x = Quarter,
y = Time,
colour = event
)) +
geom_point() +
geom_line(aes(group = ID)) +
scale_x_continuous(labels = unique(df$Split_Q))

Combine stat_compare_means with facet in r: calculates p value only for 1 facet

I try to plot my data using this R code:
print(ggplot(data = my_data3, aes(x = Visit, y = Variable1, group = number)) +
geom_point(aes(col=Treatment), size = 2) +
geom_line(aes(col=Treatment)) +
facet_grid(. ~ Treatment) +
ggtitle("Variable1")+
theme_bw() +
stat_compare_means(comparisons = list(c("visit 1", "visit 2")), label = "p.format", method = "wilcox.test", paired=T, tip.length = 0))
My Variable3 contains 2 variables that are plotted as 2 graphs when I use the facet_grid function. However, the p value is only shown for one of the plots. How can I get the p value for both plots?Graph showing the p value for 1 facet
This is part of the dataset:
my_data3 <- structure(list(number = c(110002, 110002, 110003, 110003, 110004,
110004, 110005, 110005, 110006, 110006, 110007, 110007, 110008,
110008, 110009, 110009, 110010, 110010, 110011, 110011, 110012,
110012, 110013, 110013, 110014, 110014, 110016, 110016, 110017,
110017), Treatment = c("Treatment1", "Treatment1", "Treatment2",
"Treatment2", "Treatment2", "Treatment2", "Treatment2", "Treatment2",
"Treatment1", "Treatment1", "Treatment1", "Treatment1", "Treatment2",
"Treatment2", "Treatment2", "Treatment2", "Treatment1", "Treatment1",
"Treatment2", "Treatment2", "Treatment1", "Treatment1", "Treatment2",
"Treatment2", "Treatment2", "Treatment2", "Treatment1", "Treatment1",
"Treatment2", "Treatment2"), Visit = c("visit 1", "visit 2",
"visit 1", "visit 2", "visit 1", "visit 2", "visit 1", "visit 2",
"visit 1", "visit 2", "visit 1", "visit 2", "visit 1", "visit 2",
"visit 1", "visit 2", "visit 1", "visit 2", "visit 1", "visit 2",
"visit 1", "visit 2", "visit 1", "visit 2", "visit 1", "visit 2",
"visit 1", "visit 2", "visit 1", "visit 2"), Variable1 = c(5618,
4480.5, 1034.75, 706.75, 11492.5, 6037.5, 3841.5, 2762.75, 306,
138.5, 259.5, 0, 31.5, 911.75, 1909.5, 1352.75, 1957.75, 2383.25,
23538.25, 8595.5, 13360.5, 10337.5, 1696.5, 805.25, 14655, 6169,
10141, 5922.25, 2164.25, 14990.25)), .Names = c("number", "Treatment",
"Visit", "Variable1"), row.names = c(NA, 30L), class = "data.frame")
I ran into a similar problem today, so I'll leave the answer here in case anyone else needs it in the future:
It seems that stat_compare_means struggles when you include a grouping variable in the general aesthetics of the plot (using group, color, fill, etc), so you should move these to the aesthetics of the specific function where you want to use them.
For your code, I only had to move the group = number argument inside the geom_line function and the problem was solved:
ggplot(data = my_data3, aes(x = Visit, y = Variable1)) +
geom_point(aes(col=Treatment), size = 2) +
geom_line(aes(col=Treatment, group = number)) +
facet_grid(. ~ Treatment) +
ggtitle("Variable1")+
theme_bw() +
stat_compare_means(comparisons = list(c("visit 1", "visit 2")),
label = "p.format", method = "wilcox.test", paired=T, tip.length = 0)

ggplot - legend as y-axis label

I have the following graph
Is it possible to add the legend labels (HPD and Quantile) under the respective boxplots? Also can i get rid of the white bar in the middle?
My code isthe following:
p <- ggplot(Results.Baseline,aes(x=Inference, y=Results, fill=Method)) +
scale_y_continuous(limits = c(0, 1))+
geom_boxplot()+facet_wrap(~Method)+ facet_wrap(~Model)+
geom_hline(yintercept=0.95, linetype="dashed", color = "red")
I basically want something like this just under all boxplots:
Here is my data:
data <- structure(list(Results = c(0.234375, 0.203125, 0.234375, 0.203125,
0.21875, 0.203125), Model = c("Baseline 1", "Baseline 1", "Baseline 1",
"Baseline 1", "Baseline 1", "Baseline 1"), Method = c("Quantile",
"Quantile", "Quantile", "Quantile", "Quantile", "Quantile"),
Inference = c("HMDM", "HMDM", "HMDM", "HMDM", "HMDM", "HMDM"
)), .Names = c("Results", "Model", "Method", "Inference"), row.names = c("1:nrow(transitions)",
"V2", "V3", "V4", "V5", "V6"), class = "data.frame")
I added more data so that I can replicate your graph better. You can
use geom_text to add the Method labels to the graph. You have to
only keep one label per box plot which is why I created the datalabs
dataframe. Also you did not need two facet_wraps in your plot. Does
this help answer your question?
data <- structure(list(Results = c(0.234375, 0.203125, 0.234375, 0.203125,
0.21875, 0.203125), Model = c("Baseline 1", "Baseline 1", "Baseline
1",
"Baseline 1", "Baseline 1", "Baseline 1"), Method = c("Quantile",
"Quantile", "Quantile", "Quantile", "Quantile", "Quantile"),
Inference = c("HMDM", "HMDM", "HMDM", "HMDM", "HMDM", "HMDM"
)), .Names = c("Results", "Model", "Method", "Inference"), row.names = c("1:nrow(transitions)",
"V2", "V3", "V4", "V5", "V6"), class = "data.frame")
data2 <- structure(list(Results = c(0.234375, 0.203125, 0.234375, 0.203125,
0.21875, 0.203125), Model = c("Baseline 2", "Baseline 2", "Baseline 2",
"Baseline 2", "Baseline 2", "Baseline 2"), Method = c("HPD",
"HPD", "HPD", "HPD", "HPD", "HPD"),
Inference = c("Eco. Inf.", "Eco. Inf.", "Eco. Inf.", "Eco. Inf.",
"Eco. Inf.", "Eco. Inf."
)), .Names = c("Results", "Model", "Method", "Inference"), row.names = c("1:nrow(transitions)",
"V2", "V3", "V4", "V5", "V6"), class = "data.frame")
data3 <- rbind(data,data2)
data4 <- mutate(data3, Method = ifelse(Method == "Quantile",
"HPD","Quantile"),
Inference = ifelse(Inference == "HMDM","Eco. Inf.",
"HMDM"))
data5 <- rbind(data3,data4)
datalabs <- data5 %>%
group_by(Method,Model) %>%
arrange(Method,Model) %>%
filter(row_number()==1)
ggplot(data5,aes(x=Inference, y=Results, fill=Method)) +
scale_y_continuous(limits = c(0, 1))+
geom_boxplot()+
facet_wrap(~Model)+
geom_hline(yintercept=0.95, linetype="dashed", color = "red")+
geom_text(data = datalabs, aes(label=Method) ,
nudge_y = -.1)+
theme_bw() +
theme(panel.grid = element_blank()) +
theme(panel.spacing = unit(0, "lines"),
strip.background = element_blank(),
panel.border = element_rect(fill = NA, color="white"))

Resources