Hi, I'm trying to make a plot of a survey question with a likert scale using ggplots. I need to help to organize the middle "neutral" values correctly. I have used two data frames, one for the left side "low_col", and one for the right side "high_col", both have the neutral value divided by 2. This is the script I used for the plot, and how the graph looks. I would highly appreciate all the advice to correct the order, and also all the help to add the percentages that I have in both data frames in a column named per. I hope someone can help me. Thanks
ggplot()+ geom_bar(data = high_col, mapping = aes(x=Q6, y=per, fill=col), position = "stack", stat = "identity")+ geom_bar(data= low_col, mapping = aes(x=Q6, y=-per, fill=col), position = "stack", stat = "identity")+ geom_hline(yintercept = 0, color=c("white"))+coord_flip() +scale_fill_identity("", labels = mylevels, breaks=legend.pal, guide="legend") + theme_fivethirtyeight() + theme(plot.title = element_text(size=14, hjust=0.5)) + theme(axis.text.y = element_text(hjust=0)) + theme(legend.position = "bottom")
The structure of the low_col and high_col is as follows:
For high_col:
dput(high_col)
structure(list(Q6 = c("General", "0", "1", "2", "General", "0", "1", "2", "3", "General", "0", "1", "2", "3"), Q75 = c("Ni satisfecho, ni insatisfecho", "Ni satisfecho, ni insatisfecho", "Ni satisfecho, ni insatisfecho", "Ni satisfecho, ni insatisfecho", "Satisfecho", "Satisfecho", "Satisfecho", "Satisfecho", "Satisfecho", "Totalmente satisfecho", "Totalmente satisfecho", "Totalmente satisfecho", "Totalmente satisfecho", "Totalmente satisfecho"), n = c(5, 1, 3, 1, 53, 25, 19, 7, 2, 104, 52, 35, 14, 3), per = c(1.48809523809524, 0.609756097560975, 2.58620689655172, 2.17391304347826, 31.547619047619, 30.4878048780487, 32.7586206896551, 30.4347826086956, 40, 61.9047619047619, 63.4146341463414, 60.3448275862069, 60.8695652173913, 60), col = c("#DFDFDF", "#DFDFDF", "#DFDFDF", "#DFDFDF", "#92C5DE", "#92C5DE", "#92C5DE", "#92C5DE", "#92C5DE", "#0571B0", "#0571B0", "#0571B0", "#0571B0", "#0571B0")), row.names = c(NA, -14L), class = c("tbl_df", "tbl", "data.frame"))
For low_col:
dput(low_col)
structure(list(Q6 = c("General", "0", "General", "0", "1", "2", "General", "0", "1", "2"), Q75 = structure(c(2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L), .Label = c("Totalmente insatisfecho", "Insatisfecho", "Ni satisfecho, ni insatisfecho"), class = "factor"), n = c(2, 2, 5, 1, 3, 1, 4, 2, 1, 1), per = c(1.19047619047619, 2.4390243902439, 1.48809523809524, 0.609756097560975, 2.58620689655172, 2.17391304347826, 2.38095238095238, 2.4390243902439, 1.72413793103448, 4.34782608695652), col = c("#F4A582", "#F4A582", "#DFDFDF", "#DFDFDF", "#DFDFDF","#DFDFDF", "#CA0020", "#CA0020", "#CA0020", "#CA0020")), row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame")).
As a reference, I'm trying to follow two blogs where some individuals already did this kind of likert plots. In the first, it uses the color "col" as fill in the geom_bar, however, in my case the order is not working properly. And the result is the graph I've attached.
In the second blog, I used the following script, but I cannot change the colors, nor the order of the legend, as the labels appear in alphabetical order, and the colors are selected by default. Thanks in advance for all the insights, and info.
ggplot()+ geom_bar(data = high_col, aes(x=Q6, y=per, fill=Q75), position = position_stack(reverse = TRUE), stat = "identity") + geom_bar(data= low_col, aes(x=Q6, y=-per, fill=Q75), position = "stack", stat = "identity") +coord_flip() + theme_fivethirtyeight() + theme(plot.title = element_text(size=14, hjust=0.5)) + theme(axis.text.y = element_text(hjust=0)) + theme(legend.position = "bottom") + scale_y_continuous(breaks = seq(-100,100, 5), limits = c(-25, 100)) + scale_color_manual(labels=c("Totalmente insatisfecho", "Insatisfecho", "Ni satisfecho, ni insatisfecho", "Satisfecho", "Totalmente satisfecho"), values=legend.pal, guide="legend")+geom_text(data = pro_labels, mapping = aes(x=Q6, y=left, label=paste(round(left), "%", sep = "")), hjust=2, color="white", size=3, position = "stack")+geom_text(data = pro_labels, mapping = aes(x=Q6, y=center, label=paste(round(center), "%")), hjust=1, color="white", size=3, position = "stack")+geom_text(data = pro_labels, mapping = aes(x=Q6, y=right, label=paste(round(right), "%")), hjust=2, color="white", size=3, position = "stack")+geom_hline(yintercept = 0, color=c("grey")) + scale_colour_manual("", values = legend.pal, guide="legend")
Updated version:
Hi, I have been trying to work this out and with the following code I got the neutral value in the middle, yet the colors do not match.
ggplot()+ geom_bar(data = high_col, aes(x=Q6, y=per, fill=Q75), position = position_stack(reverse = TRUE), stat = "identity") + geom_bar(data= low_col, aes(x=Q6, y=-per, fill=Q75), position = "stack", stat = "identity") +coord_flip() + theme_fivethirtyeight() + theme(plot.title = element_text(size=14, hjust=0.5)) + theme(axis.text.y = element_text(hjust=0)) + theme(legend.position = "bottom") + scale_y_continuous(breaks = seq(-100,100, 5), limits = c(-25, 100))+geom_text(data = pro_labels, mapping = aes(x=Q6, y=left, label=paste(round(left), "%", sep = "")), hjust=2, color="white", size=3, position = "stack")+geom_text(data = pro_labels, mapping = aes(x=Q6, y=center, label=paste(round(center), "%")), hjust=1, color="white", size=3, position = "stack")+geom_text(data = pro_labels, mapping = aes(x=Q6, y=right, label=paste(round(right), "%")), hjust=2, color="white", size=3, position = "stack")+ geom_hline(yintercept = 0, color=c("grey"))+ scale_fill_discrete(labels= c("Totalmente insatisfecho", "Insatisfecho", "Ni satisfecho, ni insatisfecho", "Satisfecho", "Totalmente satisfecho"))
The result is the second graph attached here.
Related
This is my data which I'm trying to plot
dput(results)
structure(list(ontology = c("CC", "BP", "MF", "CC", "BP", "MF",
"CC", "BP", "MF"), breadth = structure(c(3L, 3L, 3L, 2L, 2L,
2L, 1L, 1L, 1L), .Label = c("10", "30", "100"), class = "factor"),
enrichment = c(4.09685904270847, 8.04193317540539, 5.5801230522415,
4.52127958016442, 8.9221766387218, 5.68189764335457, 4.25046722366786,
9.49038239297713, 6.75423163834793), p = c(0, 0, 0, 0, 0,
0, 2.09057402562873e-221, 0, 0)), class = "data.frame", row.names = c(NA,
-9L))
My code
results = read.delim("data/GO/LC-GO-enrichment_new.txt") %>%
mutate(breadth = factor(breadth))
p = ggplot(results, aes(x = breadth, y = enrichment, fill = ontology,
color = ontology)) +
geom_col(position = 'dodge', width = 0.8) +
labs(x = "Breadth", y = "Odds ratio") +
scale_fill_manual(values = ryb8[c(1, 5, 8)], name = "Ontology") +
scale_color_manual(values = darken(ryb8[c(1, 5, 8)], 1.3),
name = "Ontology") +
scale_y_log10(expand = c(0.01, 0)) +
sci_theme
p
I get something like this
is there a way the pvalue can be added similar to this
or its done post making the figure manually .
Any help or suggestion would be really helpfu;
You could simply add the p values as a text layer. Note though, that in your data, each bar has a p value, so it's not clear where the groupwise p values are coming from.
library(ggplot2)
ggplot(results, aes(x = breadth, y = enrichment, fill = ontology)) +
geom_col(position = 'dodge', width = 0.8,
aes(color = after_scale(colorspace::darken(fill, 1.3)))) +
geom_text(aes(label = paste("p", scales::pvalue(p)), group = ontology),
vjust = -1, position = position_dodge(width = 0.8)) +
labs(x = "Breadth", y = "Odds ratio", fill = "Ontology") +
scale_fill_manual(values = c("#d63228", "#dff2f8", "#4575b5")) +
scale_y_log10(expand = c(0.05, 0)) +
theme_classic(base_size = 16) +
theme(legend.position = "top")
I have a graph grouped by color with values in text above each point. However, I'd like the writing in black as it's difficult to read.
Could I get some help changing the color of the text from geom_text() to black without losing the positioning?
Adding color = "black" to geom_text() messes up the position of the text, but I'm not sure why...
My data:
structure(list(type = c("full", "full", "full", "noadiposity",
"noadiposity", "noadiposity", "nocv", "nocv", "nocv", "nocv2",
"nocv2", "nocv2", "noenergy", "noenergy", "noenergy", "noenergy2",
"noenergy2", "noenergy2"), fi.cat = structure(c(1L, 2L, 3L, 1L,
2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L), .Label = c("Non-frail",
"Pre-frail", "Frail"), class = "factor"), mean = c(0.0566154812663495,
0.150817937965167, 0.285714285714286, 0.0459153181095795, 0.148380746409361,
0.292192760942761, 0.0550705669171458, 0.147270820014587, 0.288461538461538,
0.0530093023576546, 0.145279762712841, 0.292717236467236, 0.0531040684693624,
0.146793227463497, 0.292499719195777, 0.054311319499867, 0.14824350913368,
0.283745781777278), sd = c(0.0289882935363143, 0.0342654979144937,
0.0393662413936823, 0.0298601819635622, 0.0345078387756546, 0.0422635938212309,
0.0285280200524055, 0.0338893364029561, 0.0430877768970245, 0.0275365612798787,
0.0358119253511248, 0.0415426999110631, 0.0270394224053038, 0.0374836297491701,
0.0384867847822804, 0.0280882098015465, 0.0353023978795509, 0.039235018559239
)), row.names = c(NA, -18L), groups = structure(list(type = c("full",
"noadiposity", "nocv", "nocv2", "noenergy", "noenergy2"), .rows = structure(list(
1:3, 4:6, 7:9, 10:12, 13:15, 16:18), ptype = integer(0), class = c("vctrs_list_of",
"vctrs_vctr", "list"))), row.names = c(NA, -6L), class = c("tbl_df",
"tbl", "data.frame"), .drop = TRUE), class = c("grouped_df",
"tbl_df", "tbl", "data.frame"))
The code I used:
library(ggplot2)
ggplot(grouped_mean, aes(x = fi.cat, y = mean, color = type)) +
geom_point(position = position_dodge(0.9), size = 2) +
geom_errorbar(aes(ymin = mean-sd, ymax = mean+sd), position = position_dodge(0.9), size = 1, width = 0.2) +
geom_text(aes(label = round(mean, 2)), vjust = -5.5, position = position_dodge(0.9), size = 3) +
labs(x = "FI category", y = "Mean FI score", color = "FI type") +
scale_color_brewer(palette = "Blues") +
theme_minimal()
Using the colour for the points and error bars automatically splits them into groups. If you're assigning the colour manually, you need to specify the groups in the geom_text() i.e:
ggplot(grouped_mean, aes(x = fi.cat, y = mean, color = type)) +
geom_point(position = position_dodge(0.9), size = 2) +
geom_errorbar(aes(ymin = mean-sd, ymax = mean+sd), position = position_dodge(0.9), size = 1, width = 0.2) +
# Add grouping and manual colour to geom_text
geom_text(aes(label = round(mean, 2), group=type), colour="black", vjust = -5.5, position = position_dodge(0.9), size = 3) +
labs(x = "FI category", y = "Mean FI score", color = "FI type") +
scale_color_brewer(palette = "Blues") +
theme_minimal()
Here is an approach: Not the best one, but it seems to work!
This approach uses fill aesthetics and assigns the color aesthetics separately to geom_text aesthetics:
library(ggplot2)
ggplot(grouped_mean, aes(x = fi.cat, y = mean, fill=type)) +
geom_point(position = position_dodge(0.9), size = 2) +
geom_errorbar(aes(ymin = mean-sd, ymax = mean+sd), position = position_dodge(0.9), size = 1, width = 0.2) +
geom_text(aes(label = round(mean, 2)), vjust =-11.5, position = position_dodge(0.9), size = 3) +
labs(x = "FI category", y = "Mean FI score", color = "FI type") +
geom_point(aes(color=type), position = position_dodge(0.9), size = 2) +
geom_errorbar(aes(color=type, ymin = mean-sd, ymax = mean+sd), position = position_dodge(0.9), size = 1, width = 0.2) +
scale_color_brewer(palette = "Blues") +
theme_minimal()+
guides(fill = "none")
This is what is the output.I have a data set which contains unit, weight of each unit and compliance score for each unit in year 2016.
I was not able to add the table but here is the screenshot for the data in csv
I have named the columns in the data as unit, weight and year(which is compliance score) .
I want to create a sunburst chart where the first ring will be the unit divided based on weight and the second ring will be the same but will have labels compliance score.
The colour for each ring will be different.
I was able to do some code with the help from an online blog and the output I have gotten is similar to what I want but I am facing difficulty in positioning of the labels and also the colour coding for each ring
#using ggplot
library(ggplot2) # Visualisation
library(dplyr) # data wrangling
library(scales) # formatting
#read file
weight.eg = read.csv("Dummy Data.csv", header = FALSE, sep =
";",encoding = "UTF-8")
#change column names
colnames(weight.eg) <- c ("unit","weight","year")
#as weight column is factor change into integer
weight.eg$weight = as.numeric(levels(weight.eg$weight))
[as.integer(weight.eg$weight)]
weight.eg$year = as.numeric(levels(weight.eg$year))
[as.integer(weight.eg$year)]
#Nas are introduced, remove
weight.eg <- na.omit(weight.eg)
#Sum of the total weight
sum_total_weight = sum(weight.eg$weight)
#First layer
firstLevel = weight.eg %>% summarize(total_weight=sum(weight))
sunburst_0 = ggplot(firstLevel) # Just a foundation
#this will generate a bar chart
sunburst_1 =
sunburst_0 +
geom_bar(data=firstLevel, aes(x=1, y=total_weight),
fill='darkgrey', stat='identity') +
geom_text(aes(x=1, y=sum_total_weight/2, label=paste("Total
Weight", comma(total_weight))), color='black')
#View
sunburst_1
#this argument is used to rotate the plot around the y-axis which
the total weight
sunburst_1 + coord_polar(theta = "y")
sunburst_2=
sunburst_1 +
geom_bar(data=weight.eg,
aes(x=2, y=weight.eg$weight, fill=weight.eg$weight),
color='white', position='stack', stat='identity', size=0.6)
+
geom_text(data=weight.eg, aes(label=paste(weight.eg$unit,
weight.eg$weight), x=2, y=weight.eg$weight), position='stack')
sunburst_2 + coord_polar(theta = "y")
sunburst_3 =
sunburst_2 +
geom_bar(data=weight.eg,
aes(x=3, y=weight.eg$weight,fill=weight.eg$weight),
color='white', position='stack', stat='identity',
size=0.6)+
geom_text(data = weight.eg,
aes(label=paste(weight.eg$year),x=3,y=weight.eg$weight),position =
'stack')
sunburst_3 + coord_polar(theta = "y")
sunburst_3 + scale_y_continuous(labels=comma) +
scale_fill_continuous(low='white', high='darkred') +
coord_polar('y') + theme_minimal()
Output for dput(weight.eg)
structure(list(unit = structure(2:7, .Label = c("", "A", "B",
"C", "D", "E", "F", "Unit"), class = "factor"), weight = c(30,
25, 10, 17, 5, 13), year = c(70, 80, 50, 30, 60, 40)), .Names =
c("unit",
"weight", "year"), row.names = 2:7, class = "data.frame", na.action
= structure(c(1L,
8L), .Names = c("1", "8"), class = "omit"))
output for dput(firstLevel)
structure(list(total_weight = 100), .Names = "total_weight", row.names
= c(NA,
-1L), na.action = structure(c(1L, 8L), .Names = c("1", "8"), class =
"omit"), class = "data.frame")
So I think I might have some sort of solution for you. I wasn't sure what you wanted to color-code on the outer ring; from your code it seems you wanted it to be the weight again, but it was not obvious to me. For different colour scales per ring, you could use the ggnewscale package:
library(ggnewscale)
For the centering of the labels you could write a function:
cs_fun <- function(x){(cumsum(x) + c(0, cumsum(head(x , -1))))/ 2}
Now the plotting code could look something like this:
ggplot(weight.eg) +
# Note: geom_col is equivalent to geom_bar(stat = "identity")
geom_col(data = firstLevel,
aes(x = 1, y = total_weight)) +
geom_text(data = firstLevel,
aes(x = 1, y = total_weight / 2,
label = paste("Total Weight:", total_weight)),
colour = "black") +
geom_col(aes(x = 2,
y = weight, fill = weight),
colour = "white", size = 0.6) +
scale_fill_gradient(name = "Weight",
low = "white", high = "darkred") +
# Open up new fill scale for next ring
new_scale_fill() +
geom_text(aes(x = 2, y = cs_fun(weight),
label = paste(unit, weight))) +
geom_col(aes(x = 3, y = weight, fill = weight),
size = 0.6, colour = "white") +
scale_fill_gradient(name = "Another Weight?",
low = "forestgreen", high = "white") +
geom_text(aes(label = paste0(year), x = 3,
y = cs_fun(weight))) +
coord_polar(theta = "y")
Which looks like this:
I have this code:
ggplot(databoth, aes(withxstep)) +
geom_point(aes(y = withnassoc, colour = "withnassoc"), size = 2.8) +
geom_point(aes(y = withoutnassoc, colour = "withoutnassoc"), size = 1 ) +
labs(colour = "Legend") +
labs(x = "Time") +
labs(y = "N associations")
How do I modify the withnassoc and the withoutnassoc? I would like it to be "With Activities" and "Without activities".
This should answer your question:
ggplot(databoth, aes(withxstep)) +
geom_point(aes(y = withnassoc, colour = "withnassoc"), size = 2.8) +
geom_point(aes(y = withoutnassoc, colour = "withoutnassoc"), size = 1 ) +
labs(colour = "Legend", x = "Time", y = "N associations") +
scale_color_manual(values = c("red", "blue"),
labels = c("With Activities", "Without activities"))
For this example data-set:
exampledata <- structure(list(withxstep = structure(c(4L, 3L, 2L, 1L),
.Label = c("2017-06-27", "2017-06-28", "2017-06-29", "2017-06-30"), class = "factor"),
withnassoc = c(1, 2, 3, 4), withoutnassoc = c(5, 6, 7, 8)), .Names = c("withxstep",
"withnassoc", "withoutnassoc"), class = "data.frame", row.names = c(NA,-4L))
This would be the plot:
So I have data frame
dput(df)
structure(list(Frequency = structure(c(1L, 2L, 3L, 4L, 1L, 2L,
3L, 4L), .Label = c("2", "3", "4", "5"), class = "factor"), Prcentage = c(1,
33, 58, 8, 2, 40, 53, 5), label = list("Insufficient", "Average",
"Good", "Excellent", "Insufficient", "Average", "Good", "Excellent"),
name = c("implementation", "implementation", "implementation",
"implementation", "energy", "energy", "energy", "energy")), .Names = c("Frequency",
"Prcentage", "label", "name"), row.names = c(NA, 8L), class = "data.frame")
And with following code
# Get the levels for type in the required order
df$label = factor(df$label, levels = c("Unacceptable","Insufficient", "Average","Good","Excellent"))
df = arrange(df, name, desc(label))
# Format the labels and calculate their positions
df = ddply(df, .(name), transform, pos = (cumsum(Prcentage) - 0.5 * Prcentage))
df$label1 = paste0(sprintf("%.0f", df$Prcentage), "%")
# Plot
ggplot(df, aes(x = factor(name), y = Prcentage, fill = label, order=desc(label))) +
geom_bar(stat = "identity", width = 0.5) +
geom_text(aes(y = pos, label = label1), size = 4) + theme_classic() +
scale_y_continuous(position = "top",expand = c(0, 0),breaks = seq(min(0), max(0,102), by = 10),limits = c(0,102),labels = dollar_format(suffix = "%", prefix = "")) +
coord_flip() +
xlab("") + ylab("") +
theme(legend.position="bottom",legend.title = element_blank()) +
scale_fill_manual(values = c("#ff0000","#fff68f","#b2b2b2","#1baf05","#006080"),drop = FALSE)
I produce the following plot
But now I am struggling to get the bars in reverse order. Sm my output should be reverse stacked with the right values in bars (e.g. 1% yellow should be positioned first in the left side of the plot, then follows 33%, then 56% and far right 8%). I've already tried to do this with adding
+ geom_col(position = position_stack(reverse = TRUE)) (after geom_bar)
Which produced this
But this in not correct as values in bars are not correct.
I've also looked here
How to control ordering of stacked bar chart using identity on ggplot2
Reverse fill order for histogram bars in ggplot2
Order Stacked Bar Graph in ggplot
Reverse fill order for histogram bars in ggplot2
The position of the labels is directly set by the pos value, you need to reverse that f you reverse the stack order:
ggplot(df, aes(x = factor(name))) +
geom_col(aes(y = Prcentage, fill = label),
position = position_stack(reverse = TRUE),
width = .5) +
# Set the position to its complementary
geom_text(aes(y = 100 - pos, label = label1)) +
# Rest of theme
coord_flip() +
scale_y_continuous(position = "top",
expand = c(0, 0),
breaks = seq(min(0), max(0,102), by = 10),
limits = c(0,102),
labels = dollar_format(suffix = "%", prefix = "")) +
scale_fill_manual(values = c("#ff0000","#fff68f","#b2b2b2","#1baf05","#006080"), drop = FALSE) +
xlab("") + ylab("") +
theme_classic() +
theme(legend.position="bottom",legend.title = element_blank())