R: Updating Hover Text - r
I am using the R programming language. I made the following interactive graph using the plotly library:
library(dplyr)
library(ggplot2)
library(shiny)
library(plotly)
library(htmltools)
library(dplyr)
#generate data
set.seed(123)
######
var = rnorm(731, 85,25)
date= seq(as.Date("2014/1/1"), as.Date("2016/1/1"),by="day")
data = data.frame(var,date)
vals <- 90:100
combine <- vector('list', length(vals))
count <- 0
for (i in vals) {
data$var_i = i
data$new_var_i = ifelse(data$var >i,1,0)
#percent of observations greater than i (each month)
aggregate_i = data %>%
mutate(date = as.Date(date)) %>%
group_by(month = format(date, "%Y-%m")) %>%
summarise( mean = mean(new_var_i))
#combine files together
aggregate_i$var = i
aggregate_i$var = as.factor(aggregate_i$var)
count <- count + 1
combine[[count]] <- aggregate_i
}
result_2 <- bind_rows(combine)
result_2$group = "group_b"
result_2$group = as.factor(result_2$group)
graph <-ggplot(result_2, aes(frame = var, color = group)) + geom_line(aes(x=month, y=mean, group=1))+ theme(axis.text.x = element_text(angle=90)) + ggtitle("title") + facet_wrap(. ~ group)
graph = ggplotly(graph)
When the user moves the mouse over any point on the graph, the following information is displayed (hover text):
I am trying to add more information to the hover text. For example:
result_2$tot = mean(result_2$mean)
> head(result_2)
# A tibble: 6 x 5
month mean var group tot
<chr> <dbl> <fct> <fct> <dbl>
1 2014-01 0.387 90 group_b 0.364
2 2014-02 0.429 90 group_b 0.364
3 2014-03 0.452 90 group_b 0.364
4 2014-04 0.367 90 group_b 0.364
5 2014-05 0.355 90 group_b 0.364
6 2014-06 0.433 90 group_b 0.364
Yet, when I make a new graph using this result_2 file, the new information does not appear in the hover text:
graph <-ggplot(result_2, aes(frame = var, color = group)) + geom_line(aes(x=month, y=mean, group=1))+ theme(axis.text.x = element_text(angle=90)) + ggtitle("title") + facet_wrap(. ~ group)
graph = ggplotly(graph)
#view graph
graph
Can someone please shoe me how to fix this problem?
Thanks
If you want full control of your hoverinfo its actually best to create a plotly chart rather than a ggplot and then use ggplotly(). If you have only one group in result_2 as in your example above you can use
result_2 %>%
plot_ly(x=~month, y=~mean, color=~group) %>%
group_by(group) %>%
add_lines(frame=~var,hoverinfo = "text",
text = ~ paste0("Month: ",month, "<br>",
"Mean: ", mean, "<br>",
"Total: ", mean(mean))) %>%
layout(title = list(text = "title"),
xaxis = list(tickangle = -90, tickformat = "%m-%Y"))
or if you have > 1 group in result_2 and you want to facet by group as indicated in your ggplot you can do:
result_2 %>%
group_by(group) %>%
do(
plot = plot_ly(data =., x=~month, y=~mean, color=~group) %>%
add_lines(frame=~var,hoverinfo = "text",
text = ~ paste0("Month: ",month, "<br>",
"Mean: ", mean, "<br>",
"Total: ", mean(mean))) %>%
layout(title = list(text = "title"),
xaxis = list(tickangle = -90, tickformat = "%m-%Y"))
) %>%
subplot(shareX = TRUE, shareY = FALSE, nrows = 2)
But this won't work if you have only one group hence the two options provided.
You can create any function and write anything you want in the text = ~paste0() part and it will show up in your hoverinfo.
Related
gganimate does not stop at the defined value
Update: Sorry I forgot to add the vector: time=1:100 value = 1:67 fill = rep(max(value), 100-max(value)) I want to make an animated stacked bar, Here is my example: library(tidyverse) library(gganimate) #example data frame df <- tibble(time = time, value = c(value, fill), x = "A") %>% mutate(fill_color = "gold") %>% mutate(gold_nr = value) %>% mutate(blue_nr = rev(gold_nr)) %>% pivot_longer(c(gold_nr, blue_nr), names_to = "color_group", values_to = "value_group") # the code: p <- df %>% ggplot(aes("", value_group, fill=color_group)) + geom_col(width = 0.3, position = position_fill())+ scale_fill_manual(values = c("gold", "steelblue"))+ theme_minimal()+ # theme(legend.position="none")+ transition_manual(value)+ coord_flip() animate(p, fps=24, renderer = gifski_renderer(loop = FALSE)) My question is: Why does the bar not stop at 67 and jumps over 75? I think I have to organize the data in a other way?
You should use time column to group the frames. tail(df, 4) # time fill_color color_group value_group # 197 99 gold gold_nr 67 # 198 99 gold blue_nr 2 # 199 100 gold gold_nr 67 # 200 100 gold blue_nr 1 The plot now shows correctly the proportions in the last time frame. proportions(df[df$time == 100, ]$value_group) # [1] 0.98529412 0.01470588 library('magrittr') p <- df %>% ggplot2::ggplot(ggplot2::aes("", value_group, fill=color_group)) + ggplot2::geom_col(width=0.3, position=position_fill()) + ggplot2::scale_fill_manual(values=c("steelblue", "gold")) + ggplot2::theme_minimal() + ggplot2::coord_flip() + gganimate::transition_manual(time) a <- gganimate::animate(p, fps=24, renderer=gifski_renderer(loop=TRUE)) gganimate::anim_save('a.gif', a) Note, that your colors were flipped.
How to visualize multiple bar plots in one (or splitted) pdf
I'm using the tidyverse-ggplot2 combination to plot multiple bar plots. In one of my comparisons i would like to have even up to 300 single plots. I was wondering if there is a possibility to make sure that the plots will be visible in the pdf file and not look like the attached example If possible I would prefer to have all the plots in one single pdf file, but if not, also multiple pages will be ok. The command to plot the bar charts is common %>% as_tibble(rownames="gene") %>% left_join(x= ., y = up[,1:2], by = c("gene" = "ensembl_gene_id") ) %>% pivot_longer(starts_with("S"), names_to="sample", values_to="counts") %>% left_join(groups, by="sample") %>% group_by(mgi_symbol, group, cond, time) %>% summarize(mean_count=mean(counts)) %>% ggplot( aes(x = time, y = mean_count, fill=cond)) + geom_bar(stat = "identity", position = position_dodge(width=0.9) ) + scale_fill_manual(values=c("darkblue", "lightblue", "black")) + facet_wrap(~mgi_symbol, scales = "free", ncol = 5) + theme_bw() I forgot to add the group table groups <- tibble( sample= colnames(normCounts), group = rep(seq(1, ncol(normCounts)/3), each=3), cond = rep(c("WT", "GCN2-KO", "GCN1-KO"), each = 12), time = rep(rep(c("0h", "1h", "4h", "8h"), each=3), times = 3 ) ) thanks Adding the command with the group_map was as such common %>% as_tibble(rownames="gene") %>% left_join(x= ., y = up[,1:2], by = c("gene" = "ensembl_gene_id") ) %>% pivot_longer(starts_with("S"), names_to="sample", values_to="counts") %>% left_join(groups, by="sample") %>% group_by(mgi_symbol, group, cond, time) %>% summarize(mean_count=mean(counts)) %>% group_map(function(g, ...) ggplot(g, aes(x = time, y = mean_count, fill=cond)) + geom_bar(stat = "identity", position = position_dodge(width=0.9) ) + scale_fill_manual(values=c("darkblue", "lightblue", "black")) + facet_wrap(~mgi_symbol, scales = "free", ncol = 5) + theme_bw() ) EDIT This is how the data looks like in the input table (after summarizing the means) df <- common %>% as_tibble(rownames="gene") %>% left_join(x= ., y = up[,1:2], by = c("gene" = "ensembl_gene_id") ) %>% pivot_longer(starts_with("S"), names_to="sample", values_to="counts") %>% left_join(groups, by="sample") %>% group_by(mgi_symbol, group, cond, time) %>% summarize(mean_count=mean(counts)) %>% ungroup() df #>`summarise()` regrouping output by 'mgi_symbol', 'group', 'cond' (override with `.groups` argument) #> # A tibble: 1,212 x 5 #> mgi_symbol group cond time mean_count #> <chr> <int> <chr> <chr> <dbl> #> 1 0610031O16Rik 1 WT 0h 14.4 #> 2 0610031O16Rik 2 WT 1h 30.9 #> 3 0610031O16Rik 3 WT 4h 45.5 #> 4 0610031O16Rik 4 WT 8h 56.0 #> 5 0610031O16Rik 5 GCN2-KO 0h 18.9 #> 6 0610031O16Rik 6 GCN2-KO 1h 39.4 #> 7 0610031O16Rik 7 GCN2-KO 4h 13.9 #> 8 0610031O16Rik 8 GCN2-KO 8h 13.3 #> 9 0610031O16Rik 9 GCN1-KO 0h 12.3 #> 10 0610031O16Rik 10 GCN1-KO 1h 25.3 #> # … with 1,202 more rows
Start with some dummy data. This is the data after you've finished running left_join, pivot_longer, group_by, summarize. library(tidyverse) df <- tibble( time = 1:5, mean_count = 1:5, cond = "x" ) %>% expand_grid(mgi_symbol = c(letters, LETTERS)) Create a column group which represents what page the mgi_symbol belongs on. plots_per_page <- 20 df <- df %>% mutate(group = (dense_rank(mgi_symbol) - 1) %/% plots_per_page) Create all the plots with group_map. plots <- df %>% group_by(group) %>% group_map(function(g, ...) { ggplot(g, aes(x = time, y = mean_count, fill=cond)) + geom_bar(stat = "identity", position = position_dodge(width=0.9) ) + scale_fill_manual(values=c("darkblue", "lightblue", "black")) + facet_wrap(~mgi_symbol, scales = "free", ncol = 5) + theme_bw() }) Save as multiple pages using ggpubr ggpubr::ggexport( ggpubr::ggarrange(plotlist = plots, nrow = 1, ncol = 1), filename = "plots.pdf" )
Dygraphs in R: Plot Ribbon and mean line of different groups
I recently started working dygraphs in R, and wanted to achieve a ribbon line plot with it. Currently, I have the below ggplot which displays a ribbon (for data from multiple batches over time) and its median for two groups. Below is the code for it. ggplot(df, aes(x=variable, y=A, color=`[category]`, fill = `[category]`)) + stat_summary(geom = "ribbon", alpha = 0.35) + stat_summary(geom = "line", size = 0.9) + theme_minimal()+ labs(x="TimeStamp") I could add the median solid line on the dygraph, but I'm unable to add the ribbon to it. Below is the dygraph and my code for it. df_Medians<- df%>% group_by(variable,`[category]`) %>% summarise(A = median(A[!is.na(A)])) median <- cbind(as.ts(df_Medians$A)) dygraph(median) %>% dyRangeSelector() Is there anyway to plot something similar to the above ggplot on dygraphs? Thanks in advance.
See if the following serves your purpose: ggplot code (for mean, replace median_se with mean_se in the stat_summary layers): library(ggplot2) ggplot(df, aes(x=variable, y=A, color=category, fill = category)) + stat_summary(geom = "ribbon", alpha = 0.35, fun.data = median_se) + stat_summary(geom = "line", size = 0.9, fun.data = median_se) + theme_minimal() dygraph code (for mean, replace median_se with mean_se in the summarise step): library(dplyr) library(dygraph) # calculate summary statistics for each category, & spread results out such that each row # corresponds to one position on the x-axis df_dygraph <- df %>% group_by(variable, category) %>% summarise(data = list(median_se(A))) %>% ungroup() %>% tidyr::unnest(data) %>% mutate(category = as.integer(factor(category))) %>% # optional: standardizes the column # names for summary stats tidyr::pivot_wider(id_cols = variable, names_from = category, values_from = c(ymin, y, ymax)) > head(df_dygraph) # A tibble: 6 x 7 variable ymin_1 ymin_2 y_1 y_2 ymax_1 ymax_2 <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 1 1 3817. 2712. 4560. 2918. 5304. 3125. 2 2 3848. 2712. 4564. 2918. 5279. 3125. 3 3 3847. 2826. 4564 2961 5281. 3096. 4 4 3722. 2827. 4331 2962. 4940. 3098. 5 5 3833. 2831. 4570. 2963 5306. 3095. 6 6 3835. 2831. 4572 2964 5309. 3097. dygraph(df_dygraph, main = "Dygraph title") %>% dySeries(c("ymin_1", "y_1", "ymax_1"), label = "Category 1") %>% dySeries(c("ymin_2", "y_2", "ymax_2"), label = "Category 2") %>% dyRangeSelector() Code for median counterpart of mean_se: median_se <- function(x) { x <- na.omit(x) se <- sqrt(var(x) / length(x)) med <- median(x) ggplot2:::new_data_frame(list(y = med, ymin = med - se, ymax = med + se), n = 1) } Sample data: df <- diamonds %>% select(price, cut) %>% filter(cut %in% c("Fair", "Ideal")) %>% group_by(cut) %>% slice(1:1000) %>% mutate(variable = rep(seq(1, 50), times = 20)) %>% ungroup() %>% rename(A = price, category = cut)
How to change markers on time series with plotly?
I have a dataframe containing time series data, formed by 3 columns. time, variable and category. I want to plot the time in the x axis and the variable in the y axis, and I want to make groups based on category. Additionally, I would like to modify the default markers created by plotly, so they display a rounded value of the variable. Consider the following example: var = rnorm(150) var[51:100] = var[51:100] +5 var[101:150] = var[101:150] +10 time = seq(as.Date('2018-01-01'), as.Date('2018-01-01')+49, by = 'days') df = tibble(var = var, time = rep(time, 3), category = c(rep('a', 50), rep('b', 50), rep('c', 50))) head(df) var time category <dbl> <date> <chr> 1 0.330 2018-01-01 a 2 -0.786 2018-01-02 a 3 -0.838 2018-01-03 a 4 -0.0719 2018-01-04 a 5 0.0320 2018-01-05 a 6 -1.16 2018-01-06 a library(plotly) df %>% group_by(category) %>% plot_ly(x = ~ time, y = ~ var, color = ~ category, mode = 'lines+markers') This generates the kind of plot that I want: see here, but when I try to modify the the markers: df %>% group_by(category) %>% plot_ly(x = ~ time, y = ~ var, color = ~ category, mode = 'lines+markers') %>% add_markers(text = ~ paste("<b>Variable:</b> ", round(var, 2), "<br />", "<b>Time:</b> ", time), hoverinfo = "text") It transforms the plot drawing just the dots but not the lines.see here. If I try to force adding the lines with the command add_lines() then I have a double legend, with values for the dots and the lines separatedly. df %>% group_by(category) %>% plot_ly(x = ~ time, y = ~ var, color = ~ category, mode = 'lines+markers') %>% add_markers(text = ~ paste("<b>Variable:</b> ", round(var, 2), "<br />", "<b>Time:</b> ", time), hoverinfo = "text") %>% add_lines() Is there a way to plot a time series with plotly that includes lines, and customized markers? Im sorry if this is a silly question, I am quite new to plotly.
If you want one trace with both markers and lines then stick with the plot_ly function instead of adding traces. Try this: library(plotly) df %>% group_by(category) %>% plot_ly(x = ~ time, y = ~ var, color = ~ category, mode = 'lines+markers', type = "scatter", text = ~ paste("<b>Variable:</b> ", round(var, 2), "<br />", "<b>Time:</b> ", time), hoverinfo = "text")
Barplot Indicating the statistically significant difference
I need to draw a bar plot for significant SNP codes (categorical) against the corresponding phenotype, similar to these plots: I tried many ways in R and got some results but I field to got my favorite result. Here are the codes and results: ### DATA SNP_code <- as.factor(c("GG","GA","AA","GA","GA","GG","GG","GG","GG","GA","GA","AA","GA","GA","GA","GG","GG","GG","GG","AA","GG","GG","GG","GG","AA","GG","GG","GA","GG","AA","GA","GG","GG","GG","GG","GG","GG","AA","GG","GA","GG","GG","GA","GG","GG","GA","GG","GG","GA","GA","GG","GA","GG","GA","GA","GA","GA","GA","GA","GG","GG","GG","AA","GA","GA","GA","GA","GG","GA","GG","GG","GG","GA","GA","GA","GG","GG","GA","GG","AA","GG","GG","GG","AA")) EBV <- c(0.06663,-0.03031,-0.122,-0.02021,-0.1157,-0.08131,-0.02034,-0.06324,0.06699,-0.062,0.02736,-0.1201,-0.04846,-0.06934,-0.06023,-0.009244,-0.05648,-0.01908,0.06728,-0.06517,0.08534,0.07618,-0.0814,0.06113,-0.0795,0.1055,0.08305,0.1209,-0.05314,-0.09431,0.05185,0.1347,0.1591,0.08777,0.08326,0.1612,0.09528,-0.1002,0.1561,-0.09327,0.09474,0.1356,0.06384,0.1585,0.03235,0.1081,0.1462,-0.04082,-0.05042,0.01793,-0.1157,-0.1165,-0.009399,-0.02311,-0.108,-0.1143,0.07219,0.01376,-0.05059,-0.052,0.08494,-0.0388,-0.06346,0.07789,0.02961,-0.1126,0.1102,0.133,-0.09317,-0.1181,0.1584,0.122,0.1019,-0.04074,-0.01178,0.09523,-0.03266,-0.01258,-0.0231,-0.08259,0.05823,-0.02894,-0.008242,0.07981) LS <- c(2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,1,2,1,1,2,1,2,2,2,1,1,1,2,2,2,2,2,1,1,2,1,2,2,2,1,2,2,2,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,2,1,1,2,2,1,1,2,1,2,1,1,2,1,1,1,1,1,1,1,2) IDs <- c(1033,1081,1106,1107,1120,1194,1199,1326,1334,1340,1345,1358,1398,1404,1405,1421,1457,1459,1464,1509,1529,1542,1550,2025,2030,2095,2099,2128,2141,2153,2167,2224,2232,2238,2244,2266,2271,2280,2283,2323,2326,2337,2369,2390,2391,2396,851012,851016,851021,851055,851063,851084,851105,851109,851146,851169,851176,851198,851205,851246,851266,851292,851332,851345,851488,851489,851509,851528,851531,851547,851562,851573,851574,851578,851584,851588,851592,851622,851651,851670,851672,851684,851690,861086) sig_snp <- data.frame(IDs, SNP_code, EBV, LS) ### Variance analysis and Mean comparison library(dplyr) ### for LS group_by(sig_snp, SNP_code) %>% summarise( count = n(), mean = mean(LS, na.rm = TRUE), sd = sd(LS, na.rm = TRUE)) ### for EBV group_by(sig_snp, SNP_code) %>% summarise( count = n(), mean = mean(EBV, na.rm = TRUE), sd = sd(EBV, na.rm = TRUE)) # Compute the analysis of variance Anova.fit <- aov(EBV ~ SNP_code, data = sig_snp) summary(Anova.fit) # Tukey multiple pairwise-comparisons TukeyHSD(Anova.fit) # or library(multcomp) summary(glht(Anova.fit, linfct = mcp(SNP_code = "Tukey"))) ### Box plot for EBV (actually I need Barplot for LS and EBV) library(ggplot2) library(ggpval) plot <- ggplot(sig_snp, aes(SNP_code, EBV)) + geom_boxplot(fill=c("red","blue", "green"), color="black", width=.7); plot add_pval(plot, pairs = list(c(1, 3)), test='wilcox.test') add_pval(plot, pairs = list(c(2, 3)), test='wilcox.test') add_pval(plot, pairs = list(c(1, 2)), test='wilcox.test') "add_pval" only use "wilcox.test" and "t.test", but I perfer Tukey. Any help is appreciated.
There is definitely room for improvement of the code that I posted below, but at least it gives you one example of the workflow you can use for getting your "favorite" barplot: Part A: Barchart 1) We re-organise sig_snp in order to get a dataframe with the mean of each SNP in function of EBV or LS. library(tidyverse) DF1 <- sig_snp %>% pivot_longer(., cols = c(EBV,LS), names_to = "Variable", values_to = "Values") %>% group_by(SNP_code, Variable) %>% summarise(Mean = mean(Values), SEM = sd(Values) / sqrt(n()), Nb = n()) %>% rowwise() %>% mutate(Labels = as.character(SNP_code)) %>% mutate(Labels = paste(unlist(strsplit(Labels,"")),collapse = "/")) %>% mutate(Labels = paste0(Labels,"\nn = ",Nb)) # A tibble: 6 x 6 SNP_code Variable Mean SEM Nb Labels <fct> <chr> <dbl> <dbl> <int> <chr> 1 AA EBV -0.0719 0.0202 9 "A/A\nn = 9" 2 AA LS 1.11 0.111 9 "A/A\nn = 9" 3 GA EBV -0.0141 0.0134 31 "G/A\nn = 31" 4 GA LS 1.23 0.0763 31 "G/A\nn = 31" 5 GG EBV 0.0422 0.0126 44 "G/G\nn = 44" 6 GG LS 1.48 0.0762 44 "G/G\nn = 44" The labels column will be re-used later for the labeling of x-axis. 2) Then, we are going to calculate the total mean (that will hep to draw the "Mean" bar) by doing: library(tidyverse) DF2 <- sig_snp %>% pivot_longer(., cols = c(EBV,LS), names_to = "Variable", values_to = "Values") %>% group_by(Variable) %>% summarise(Mean = mean(Values), SEM = sd(Values) / sqrt(n()), Nb = n()) %>% mutate(SNP_code = "All") %>% select(SNP_code, Variable, Mean, SEM, Nb) %>% rowwise() %>% mutate(Labels = paste0("Mean\nn = ",Nb)) # A tibble: 2 x 6 SNP_code Variable Mean SEM Nb Labels <chr> <chr> <dbl> <dbl> <int> <chr> 1 All EBV 0.00918 0.00944 84 "Mean\nn = 84" 2 All LS 1.35 0.0522 84 "Mean\nn = 84" 3) we are binding both DF1 and DF2 and we re-organize the levels of SNP_code in order to get the correct plotting order: library(tidyverse) DF <- bind_rows(DF1, DF2) DF$Labels = factor(DF$Labels,levels= c("Mean\nn = 84", "A/A\nn = 9", "G/A\nn = 31", "G/G\nn = 44" )) 4) Now, we can plot it: library(ggplot2) ggplot(DF, aes(x = SNP_code, y = Mean, fill = SNP_code))+ geom_bar(stat = "identity", show.legend = FALSE)+ geom_errorbar(aes(ymin = Mean-SEM, ymax = Mean+SEM), width = 0.2)+ facet_wrap(.~Variable, scales = "free")+ scale_x_discrete(name = "",labels = levels(DF$Labels)) Part B: Adding statistic on the barchart For adding statistic, you can have the use of geom_signif function from ggsignif package that allow to add statistics from an external output. 1) First create the dataframe for the output of Tukey test on EBV: Anova.fit <- aov(EBV ~ SNP_code, data = sig_snp) t <- TukeyHSD(Anova.fit) stat <- t$SNP_code Stat_EBV <- stat %>% as.data.frame() %>% mutate(Variable = "EBV") %>% mutate(Group = rownames(stat)) %>% rowwise() %>% mutate(Group1 = unlist(strsplit(Group,"-"))[1]) %>% mutate(Group2 = unlist(strsplit(Group,"-"))[2]) %>% mutate(labels = round(`p adj`,4)) Stat_EBV$y_pos <- c(0.06,0.08,0.1) 2) same thing for the Tukey test of LS: Anova.fit <- aov(LS ~ SNP_code, data = sig_snp) t <- TukeyHSD(Anova.fit) stat <- t$SNP_code Stat_LS <- stat %>% as.data.frame() %>% mutate(Variable = "LS") %>% mutate(Group = rownames(stat)) %>% rowwise() %>% mutate(Group1 = unlist(strsplit(Group,"-"))[1]) %>% mutate(Group2 = unlist(strsplit(Group,"-"))[2]) %>% mutate(labels = round(`p adj`,4)) Stat_LS$y_pos = c(1.7,1.9,2.1) 3) Binding of both stats dataframes: library(tidyverse) STAT <- bind_rows(Stat_EBV,Stat_LS) # A tibble: 6 x 10 diff lwr upr `p adj` Variable Group Group1 Group2 labels y_pos <dbl> <dbl> <dbl> <dbl> <chr> <chr> <chr> <chr> <dbl> <dbl> 1 0.0578 -0.0130 0.129 0.132 EBV GA-AA GA AA 0.132 0.06 2 0.114 0.0457 0.183 0.000431 EBV GG-AA GG AA 0.0004 0.08 3 0.0563 0.0125 0.100 0.00821 EBV GG-GA GG GA 0.0082 0.1 4 0.115 -0.303 0.532 0.790 LS GA-AA GA AA 0.790 1.7 5 0.366 -0.0373 0.770 0.0832 LS GG-AA GG AA 0.0832 1.9 6 0.251 -0.00716 0.510 0.0585 LS GG-GA GG GA 0.0585 2.1 4) Get the barchart and add the statistic results: library(ggplot2) library(ggsignif) ggplot(DF, aes(x = SNP_code, y = Mean, fill = SNP_code))+ geom_bar(stat = "identity", show.legend = FALSE)+ geom_errorbar(aes(ymin = Mean-SEM, ymax = Mean+SEM), width = 0.2)+ geom_signif(inherit.aes = FALSE, data = STAT, aes(xmin=Group1, xmax=Group2, annotations=labels, y_position=y_pos), manual = TRUE)+ facet_wrap(.~Variable, scales = "free")+ scale_x_discrete(name = "",labels = levels(DF$Labels)) I hope it looks what you are expecting.