Customize title and add text into facet? - r

Can someone please help me edit my barplot titles? I was trying edit title of the barplots in facet but somehow its not working and also i want to add text into each bar, like 'a', 'b' or 'ab' (kinda statistical interpretation).
Here is my code:
df <- data.frame(
H1 = c(6.36, 3.03, 6.85, 4.07, 4.69, 6.27, 6.67, 3.11, 5.07, 6.14, 5.93, 6.49),
H2 = c(5.15, 5.00, 5.71, 5.50, 4.99, 5.81, 6.05, 5.76, 5.28, 5.69, 5.69, 5.06),
H3 = c(3.85, 5.13, 4.99, 4.91, 5.01, 5.73, 5.77, 5.94, 5.57, 5.35, 6.00, 4.39),
H4 = c(3.84, 4.80, 5.15, 4.85, 4.99, 5.73, 5.77, 5.45, 5.44, 5.41, 5.81, 4.46),
H5 = c(4.08, 5.17, 4.77, 5.03, 5.00, 5.49, 5.49, 5.80, 5.51, 5.18, 5.76, 4.60),
H6 = c(4.35, 5.59, 5.59, 4.83, 5.52, 5.63, 5.85, 5.74, 5.66, 5.19, 5.79, 4.84), fontface = c("bold"),
names = c("Russian Banana", "Vermillion", "Atlantic", "POR12PG28-3",
"Valery", "Rio Colorado", "CO99076-6R", "Purple Majesty",
"AC99330-1P/Y", "CO05068-1RU", "Masquerade", "Canela Russet"),
specie = c(rep("Appearance", 12), rep("Aroma" , 12), rep("Flavor" , 12),
rep("Overall" , 12), rep("Aftertaste", 12), rep("Texture", 12)),
condition = rep(c("Russian Banana", "Vermillion", "Atlantic", "POR12PG28-3",
"Valery", "Rio Colorado", "CO99076-6R", "Purple Majesty",
"AC99330-1P/Y", "CO05068-1RU", "Masquerade", "Canela Russet") , 6))
df <- df %>%
pivot_longer(starts_with("H"))
nameframe <- enframe(unique(df$name))
specieframe <- enframe(unique(df$specie))
specie.labs <- c("Appearance", "Aroma", "Flavor", "Overall", "Aftertaste", "Texture")
names(specie.labs) <- c("H1", "H2", "H3", "H4", "H5", "H6")
(filtframe <- inner_join(nameframe, specieframe, by = "name") %>% mutate(
filtcont =
paste0(
"(name=='", value.x,
"' & ", "specie=='", value.y, "')"
)
))
(filtcond <- paste0(filtframe$filtcont, collapse = " | "))
df_filt <- filter(
df,
!!rlang::parse_expr(filtcond)
)
ggplot() +
geom_col(data = df_filt, mapping = aes(x = names, y = value, fill = specie), position = "dodge") +
coord_flip() +
labs(y = "", x = "") + theme(legend.title = element_blank()) +
scale_fill_discrete(breaks=c("Appearance","Aroma","Flavor", "Overall", "Aftertaste", "Texture")) +
facet_wrap(vars(name), labeller = labeller(specie = specie.labs))
enter image description here

Create a labeller like this:
map_species <- function(species) specie.labs[species]
Then use the formula notation in facet_wrap() and refer to the wrapping column (I called it h_name) in labeller():
df %>%
pivot_longer(starts_with("H"), names_to = "h_name") %>%
ggplot(aes(x = names, y = value, fill = specie)) +
geom_col(position = "dodge") +
coord_flip() +
labs(y = "", x = "") +
theme(legend.title = element_blank()) +
scale_fill_discrete(
breaks=c("Appearance","Aroma","Flavor", "Overall", "Aftertaste", "Texture")
) +
facet_wrap(~h_name, labeller = labeller(h_name = map_species))

Related

Creating a graph with multiple X axis values

I have a graph in Excel that I'd like to replicate in R if it's even possible. I am new to R, so any guidance will be appreciated.
So my data looks like this
I can include the file if anyone wants it.
Then I have this graph:
I'd like to plot the same graph as in the Excel file but using R. So, is there a way to have a kind of subset for the x-axis values that belong to the main value?
I looked through the ggplot documentation and How to plot side-by-side with sub labels and without space between subplots, but to no avail.
You can use either geom_bar(position = "dodge") or facet_wrap() to achieve your desired results. Please note that you'll need to name all your variables before plotting as it looks like the first two columns of your dataframe do not have names.
library(tidyverse)
data(mtcars)
# make a nested dataframe for example purposes
df <- mtcars %>%
rownames_to_column(var = "rowname") %>%
select(c(1:5)) %>%
pivot_longer(cols = -c(rowname)) %>%
head(n = 20)
ggplot(df, aes(x = name, y = value, fill = name)) +
geom_bar(stat = "identity") +
facet_wrap(~rowname, nrow = 1) # use facet_wrap to display nestedness
ggplot(df, aes(x = rowname, y = value, fill = name)) +
geom_bar(position = "dodge", stat = "identity")
This can be helpful
library(tidyr)
library(ggplot2)
df %>%
pivot_longer(ACI:SB) %>%
mutate(across(where(is.character), as.factor)) %>%
ggplot(aes(x = R, y = value, fill=name))+
geom_bar(stat="identity", position = "dodge", width=0.75)+
facet_wrap(~A, nrow=1, strip.position="bottom") +
theme(legend.position = "bottom") +
labs(fill="", y="", x="")
Produces:
If you want "to speak R with Excel accent" and convert this nice plot into a default excel plot, then you can add at the end of the plot theme_excel_new() from ggtheme package
library(ggthemes)
... +
theme_excel_new()
It'll give the following plot
Sample data:
structure(list(A = c(25, 25, 25, 50, 50, 50, 100, 100, 100, 250,
250, 250), R = c("R1", "R2", "R3", "R1", "R2", "R3", "R1", "R2",
"R3", "R1", "R2", "R3"), ACI = c(2.94, 1.91, 8.86, 5.03, 8.77,
1.89, 7.58, 7.24, 9.44, 5.48, 7.12, 3.89), PB = c(1.01, 9.27,
2.83, 5.91, 1.1, 8.41, 3.18, 7.83, 2.68, 2.19, 5.17, 2.69), NB = c(1.81,
5.19, 5.63, 1.29, 2.56, 7.18, 9.61, 1, 7.63, 9.48, 8.19, 3.08
), Bca = c(6.5, 9.53, 9.54, 3.4, 2.62, 1.65, 3.22, 5.1, 9.24,
5.11, 2.58, 0.46), SB = c(4.18, 8.54, 3.47, 1.31, 3.74, 6.31,
3.9, 6.9, 6.89, 5.55, 4.3, 4.53), `round(2)` = c(2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2)), class = "data.frame", row.names = c(NA,
-12L))

How to add test onto each bar?

I am trying to add text onto each bar, can someone please help me show how I can do? I am not a R user so please excuse my abilities. I appreciate your help. I got few responses earlier, like to use annotate or geomtext but i am not sure how to run them.
Here is my code:
library(viridis)
library(hrbrthemes)
library(tidyr)
library(dplyr)
library(tibble)
library(ggplot2)
df <- data.frame(
H1 = c(6.36, 3.03, 6.85, 4.07, 4.69, 6.27, 6.67, 3.11, 5.07, 6.14, 5.93, 6.49),
H2 = c(5.15, 5.00, 5.71, 5.50, 4.99, 5.81, 6.05, 5.76, 5.28, 5.69, 5.69, 5.06),
H3 = c(3.85, 5.13, 4.99, 4.91, 5.01, 5.73, 5.77, 5.94, 5.57, 5.35, 6.00, 4.39),
H4 = c(3.84, 4.80, 5.15, 4.85, 4.99, 5.73, 5.77, 5.45, 5.44, 5.41, 5.81, 4.46),
H5 = c(4.08, 5.17, 4.77, 5.03, 5.00, 5.49, 5.49, 5.80, 5.51, 5.18, 5.76, 4.60),
H6 = c(4.35, 5.59, 5.59, 4.83, 5.52, 5.63, 5.85, 5.74, 5.66, 5.19, 5.79, 4.84), fontface = c("bold"),
names = c("RB", "Ver", "Atl", "POR12PG28-3",
"Valery", "Rio", "CO99076-6R", "Purple",
"AC99330-1P/Y", "CO05068-1RU", "Masquerade", "Canela"),
specie = c(rep("Appearance", 12), rep("Aroma" , 12), rep("Flavor" , 12),
rep("Overall" , 12), rep("Aftertaste", 12), rep("Texture", 12)),
condition = rep(c("RB", "Ver", "Atl", "POR12PG28-3",
"Valery", "Rio", "CO99076-6R", "Purple",
"AC99330-1P/Y", "CO05068-1RU", "Masquerade", "Canela") , 6))
df <- df %>%
pivot_longer(starts_with("H"), names_to = "h.names")
df
#one condition per plot
nameframe <- enframe(unique(df$h.names))
specieframe <- enframe(unique(df$specie))
names.labs <- c("Appearance", "Aroma", "Flavor", "Overall", "Aftertaste", "Texture")
names(names.labs) <- c("H1", "H2", "H3", "H4", "H5", "H6")
ggplot() +
geom_col(data = df, mapping = aes(x = names, y = value),
position = "dodge") +
coord_flip() +
ylim(c(0,9)) +
scale_y_continuous(breaks=seq(0.0, 9, 3), limits=c(0, 9), labels = c("0", "3", "6", "Like\nExtremely")) +
labs(y = "", x = "") + theme(legend.title = element_blank(), axis.text.y = element_text(face = "bold", size = 11),
axis.text.x = element_text(face = "bold", size = 9)) +
scale_fill_discrete(breaks = c("Appearance", "Aroma", "Flavor", "Overall", "Aftertaste", "Texture")) +
facet_wrap(~h.names, labeller = labeller(h.names = names.labs))
#add text onto each bar
p <- p + annotate("text", label = "Test", size = 4, x = 15, y = 5)
print(p)
text(x = H,
y = y,
labels = c("ab", "e", "a", "d", "cd", "ab", "ab", "e", "c", "ab", "b", "ab"),
pos = 2)
Here is how you would add the text you had in your original question to each bar. Please note that I moved data = df, mapping = aes(x = names, y = value up into the ggplot() aesthetic where it will be applied to each layer in the plot. Next, used case_when from the dplyr package to add the bar plot labels as a new column to df. After that you pass in the new column into geom_text like so geom_text(aes(label = bar_labels, hjust = 0)) to apply the labels on the tip of each bar.
library(viridis)
library(tidyr)
library(dplyr)
library(tibble)
library(ggplot2)
df <- data.frame(
H1 = c(6.36, 3.03, 6.85, 4.07, 4.69, 6.27, 6.67, 3.11, 5.07, 6.14, 5.93, 6.49),
H2 = c(5.15, 5.00, 5.71, 5.50, 4.99, 5.81, 6.05, 5.76, 5.28, 5.69, 5.69, 5.06),
H3 = c(3.85, 5.13, 4.99, 4.91, 5.01, 5.73, 5.77, 5.94, 5.57, 5.35, 6.00, 4.39),
H4 = c(3.84, 4.80, 5.15, 4.85, 4.99, 5.73, 5.77, 5.45, 5.44, 5.41, 5.81, 4.46),
H5 = c(4.08, 5.17, 4.77, 5.03, 5.00, 5.49, 5.49, 5.80, 5.51, 5.18, 5.76, 4.60),
H6 = c(4.35, 5.59, 5.59, 4.83, 5.52, 5.63, 5.85, 5.74, 5.66, 5.19, 5.79, 4.84), fontface = c("bold"),
names = c("RB", "Ver", "Atl", "POR12PG28-3",
"Valery", "Rio", "CO99076-6R", "Purple",
"AC99330-1P/Y", "CO05068-1RU", "Masquerade", "Canela"),
specie = c(rep("Appearance", 12), rep("Aroma" , 12), rep("Flavor" , 12),
rep("Overall" , 12), rep("Aftertaste", 12), rep("Texture", 12)),
condition = rep(c("RB", "Ver", "Atl", "POR12PG28-3",
"Valery", "Rio", "CO99076-6R", "Purple",
"AC99330-1P/Y", "CO05068-1RU", "Masquerade", "Canela") , 6))
df <- df %>%
pivot_longer(starts_with("H"), names_to = "h.names")
#one condition per plot
nameframe <- enframe(unique(df$h.names))
specieframe <- enframe(unique(df$specie))
names.labs <- c("Appearance", "Aroma", "Flavor", "Overall", "Aftertaste", "Texture")
names(names.labs) <- c("H1", "H2", "H3", "H4", "H5", "H6")
#add text onto each bar
df <- df %>%
arrange(desc(names)) %>%
group_by(names) %>%
mutate(
bar_labels = case_when(
names == "Ver" ~ "ab",
names == "Valery" ~ "e",
names == "Rio" ~ "a",
names == "RB" ~ "d",
names == "Purple" ~ "cd",
names == "POR12PG28-3" ~ "ab",
names == "Masquerade" ~ "ab",
names == "CO99076-6R" ~ "e",
names == "CO05068-1RU" ~ "c",
names == "Canela" ~ "ab",
names == "Atl" ~ "b",
names == "AC99330-1P/Y" ~ "ab",
TRUE ~ as.character(NA)
))
ggplot(data = df, mapping = aes(x = names, y = value)) +
geom_col(position = "dodge") +
coord_flip() +
ylim(c(0,9)) +
scale_y_continuous(breaks=seq(0.0, 9, 3), limits=c(0, 9), labels = c("0", "3", "6", "Like\nExtremely")) +
labs(y = "", x = "") + theme(legend.title = element_blank(), axis.text.y = element_text(face = "bold", size = 11),
axis.text.x = element_text(face = "bold", size = 9)) +
scale_fill_discrete(breaks = c("Appearance", "Aroma", "Flavor", "Overall", "Aftertaste", "Texture")) +
facet_wrap(~h.names, labeller = labeller(h.names = names.labs)) +
geom_text(aes(label = bar_labels, hjust = 0))
Created on 2021-03-10 by the reprex package (v0.3.0)

Add custom tick mark to Y axis in ggplot2

I'd like to show the average for my dataset and add a tick mark on the Y-axis corresponding to this mean value - highlighted in red in the below image:
Code
plt <- ggplot(dat, aes(x = time, y = value)) +
geom_point(aes(fill = value), size = 2, alpha = 0.8, shape = 21, stroke = 0.5, color = 'black') +
scale_color_gradientn(colors = RColorBrewer::brewer.pal(4,name = 'OrRd')[-1], aesthetics = 'fill') +
geom_hline(yintercept = dat[, mean(value, na.rm = T)], color = 'black', linetype = '11', size = 1.25) +
guides(fill = F)
I can use scale_y_continuous() to add a specific break point but it messes up the grid lines and I don't know how to customize that specific tick mark (if at all possible):
plt <- plt +
scale_y_continuous(breaks = round(c(seq(from = 0, to = dat[, max(value)], by = 10), dat[, mean(value)]), digits = 1) )
Data
Reduced dataset for reproducing the plot:
structure(list(time = structure(c(1607990400, 1607996400, 1608002400,
1608008400, 1608014400, 1608020400, 1608026400, 1608032400, 1608038400,
1608044400, 1608050400, 1608056400, 1608062400, 1608068400, 1608074400,
1608080400, 1608086400, 1608092400, 1608098400, 1608104400, 1608110400,
1608116400, 1608122400, 1608128400, 1608134400, 1608140400, 1608146400,
1608152400, 1608158400, 1608164400, 1608170400, 1608176400, 1608182400,
1608188400, 1608194400, 1608200400, 1608206400, 1608212400, 1608218400,
1608224400, 1608230400, 1608236400, 1608242400, 1608248400, 1608254400,
1608260400, 1608266400, 1608272400, 1608278400, 1608284400, 1608290400,
1608296400, 1608302400, 1608308400, 1608314400, 1608320400, 1608326400,
1608332400, 1608338400, 1608344400, 1608350400, 1608356400, 1608362400,
1608368400, 1608374400, 1608380400, 1608386400, 1608392400, 1608398400,
1608404400, 1608410400, 1608416400, 1608422400, 1608428400, 1608434400,
1608440400, 1608446400, 1608452400, 1608458400, 1608464400, 1608470400,
1608476400, 1608482400, 1608488400, 1608494400, 1608500400, 1608506400,
1608512400, 1608518400, 1608524400, 1608530400, 1608536400, 1608542400,
1608548400, 1608554400, 1608560400, 1608566400, 1608572400, 1608578400,
1608584400, 1608590400, 1608596400, 1608602400, 1608608400, 1608614400,
1608620400, 1608626400, 1608632400, 1608638400), class = c("POSIXct",
"POSIXt"), tzone = "UTC"), value = c(3.87, 3.57, 4.12, 2.68,
4.85447552447552, 0, 9.85, 2.9, 0.65010183299389, 2.55242704955998,
2.94610169491525, 3.2225, 3.44, 3.2, 3.64666666666667, 3.6, 4.2236312849162,
3.56285714285714, 2.99, 2.54, 2.34, 2.245, 2.05, 2.23666666666667,
4.82, 13.81, 18.08, 4.0375, 3.96, 12.9723756906077, 23.87, 16.2053333333333,
13.0836077705828, 10.91, 5.36238095238095, 2.62, 2.5375, 2.38,
2.72, 2.345, 2.32909090909091, 3.90333333333333, 3.02166666666667,
3.94833333333333, 3.83636363636364, 4.04117647058824, 4.22139146567718,
5.57, 4.82, 3.59666666666667, 3.73873949579832, 2, 2.04, 2.57,
3.00042016806723, 3.905, 5.65, 4.271589958159, 5.28, 7.15639534883721,
5.45, 5.24295336787565, 3.11224489795918, 4.79, 2.6106976744186,
2.25, 2.08264705882353, 2.25, 2.58666666666667, 3.18682008368201,
3.24, 3.10375, 3.35833333333333, 4.39333333333333, 3.765, 7.71,
5.16117647058824, 4.95588235294118, 2.44, 2.34666666666667, 2.345,
2.375, 2.4275, 3.0975, 3.21666666666667, 4.13, 4.44663366336634,
3.60877551020408, 3.83265033407572, 3.8625, 4.2675, 6.765, 2.688,
2.43101242521859, 2.43561435803037, 2.30166666666667, 2.69, 3.18,
5.04, 4.345, 4.86529411764706, 8.57, 6.2, 6.0032, 3.82, 5.03,
7.02, 3.69716216216216, 3.00468438538206)), row.names = c(NA,
-109L), class = c("data.table", "data.frame"))
Quick, dirty, and hacky:
plt + geom_text(aes(x = dat[, min(time, na.rm = T)], y = dat[, mean(value, na.rm = T)], label = round(dat[, mean(value, na.rm = T)],1)), color = 'red', hjust = 2) + coord_cartesian(clip = 'off')
Maybe it gets you somewhere.

Y-axis values don't match the continuous values of data R

I have used the same code for similar datasets but for some reason, it is not working for this one.
This is roughly what I get. (I hid the categorical variable names)
This is the code that I have been using:
library(tidyverse)
library(ggplot2)
df%>%
arrange(desc(round), measure) %>%
mutate(concept = factor(concept, unique(concept))) %>%
ggplot() +aes(x=concept, y=measure, fill=round)+
geom_bar(stat="identity") +
theme_minimal()+
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_fill_manual(name="round", values = c("purple", "red")) +
coord_flip()+
geom_errorbar(aes(ymax=upper, ymin=lower),position=position_dodge(.9))
Here is a sample df
structure(list(concept = c("ball", "camel", "wind",
"dog", "happy", "script", "condensation", "Marxism"),
measure = c(2.45, 3.2, 3.91, 3.94, 4.31, 3.63, 4.54, 4.55), upper = c(6.46,
6.11, 7.23, 7.9, 9.17, 11.23, 11.32, 15.3), lower = c(1.56,
0.79, 1.45, 1.02, 1.65, 1.31, 1.64, 3.07), round = c("One",
"Two", "Two", "Two", "Two", "Two", "Two",
"Two")), row.names = c(NA, -8L), class = "data.frame")

Problem with ggplot: labels and error bars overlap

I made a barplot with error bars and labels written on the bars.
My problem is: I want the labels to appear on the bars and also next to the error bars. That is, I don't want labels and error bars to overlap.
An example with my code:
i <- data.frame(
nbr =c(15.18 ,11.53 ,13.37 ,9.2, 10.9, 12.23 ,9.53, 9.81, 7.86, 12.79,
22.03 ,17.64 ,18.1, 16.78 ,17.53 ,16.97 ,17.76 ,18.35 ,12.82 ,20.91,
22.09 ,19.18 ,17.54 ,18.45 ,19.83 ,16.99 ,19.69 ,19.45 ,13.07 ,21.41,
12.13 ,9.76, 10.79 ,10.74 ,12.43 ,9.65, 12.18 ,11.63 ,6.74, 12.31,
17.5, 14.75 ,15.2, 13.89 ,15.24 ,17.43 ,15.22 ,14.04,9.49, 15.86,
8.09, 5.86, 6.68, 7.34, 8.01, 6.35, 8.4, 7.4, 3.88, 6.92 ),
SD = c(4.46, 4.19, 2.27, 2.19, 5.10, 7.25, 8.42, 6.47, 6.04, 7.48, 6.38, 6.05, 3.58, 3.85,
6.94, 6.87, 6.32, 4.28, 4.10, 7.34, 7.46, 6.62, 4.28, 5.24, 8.00, 8.10, 7.73, 5.18,
5.53, 7.96, 7.46, 7.05, 4.47, 4.73, 8.15, 6.95, 5.88, 3.20, 4.01, 7.34, 7.24, 6.98,
5.98, 4.53, 4.22, 7.21, 4.02, 4.30, 1.96, 2.11, 4.98, 7.16, 8.45, 6.39, 6.20, 7.03,
6.10, 6.42, 3.77, 3.53),
x2=rep(c("a", "b", "c", "d", "e", "f", "g",
"h", "i", "j"),6),
s = c(rep(c(rep(c("3"),10),
rep(c("4"),10),
rep(c("5"),10),
rep(c("6"),10),
rep(c("7"),10),
rep(c("8"),10)),1)))
ii <- i[order(i$s, i$nbr ), ]
sn <- factor(x = 1:60, labels = ii$x2)
ii$sn <- sn
scale_x_reordered <- function(..., sep = "___") {
reg <- paste0(sep, ".+$")
ggplot2::scale_x_discrete(labels = function(x) gsub(reg, "", x), ...)
}
reorder_within <- function(x, by, within, fun = mean, sep = "___", ...) {
new_x <- paste(x, within, sep = sep)
stats::reorder(new_x, by, FUN = fun)
}
dummy2 <- data.frame(s = levels(i$s)[-1], Z = c( 4,16,16,8,4))
dummy2$s <- factor(dummy2$s)
ggplot(ii, aes(reorder_within(sn, nbr, s), nbr,
label =x2)) +
geom_bar(stat = 'identity') +
geom_text(aes(y = 0,fontface=2), angle = 90, hjust = -.05, size = 4)+
scale_x_reordered() +
facet_wrap(.~ s, scales = "free_x", ncol=2)+
#geom_text(aes(label=nbr), vjust=1.6, color="white", size=3.5)+
theme(axis.text.x = element_blank(),
axis.title=element_text(size=16),
axis.text=element_text(face = "bold"),
strip.text.x = element_text(size = 14,face="bold")
)+ geom_errorbar(aes(reorder_within(sn, nbr, s),ymin=nbr-SD, ymax=nbr+SD), width=.2, position=position_dodge(.9))
Example of expected parcel:
I want all the labels to be written next to the error bars on the bars.
Thanks for your help !
I found this solution and wanted to share it with you:
geom_text(aes(y = 0,fontface=2), angle = 90, vjust = -1, hjust = -.05, size = 4)

Resources