ggplot2 circular stacked bar chart repeats labels without any bars - r

I am trying to recreate this example using ggplot to create a circular bar chart. Except, instead of a standard bar chart, I want to create a stacked bar chart. I've been able to get pretty close, but for some reason, the labels are repeated in this circular bar chart. I think the issue is with the id that I'm creating to match the example, but I'm not sure how to fix it.
df <- structure(list(team = structure(c(1L, 2L, 3L, 4L, 5L, 6L, 7L,
8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, NA, 1L, 2L, 3L, 4L, 5L,
6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, NA, 1L, 2L, 3L,
4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, NA), .Label = c("Team1",
"Team2", "Team3", "Team4", "Team5", "Team6", "Team7", "Team8", "Team9", "Team10",
"Team11", "Team12", "Team13", "Team14", "Team15"), class = "factor"),
variable = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L,
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("variable1",
"variable2", "variable3"), class = "factor"), value = c(3.91666666666667,
3.25, 3.88888888888889, 2.83333333333333, 3.16666666666667,
2.93333333333333, 2.66666666666667, 3.4, 3.33333333333333,
3.44444444444444, 3.41666666666667, 4, 4, 3.5, 4, 3.33333333333333,
3.8, 3.5, 3.86666666666667, 3, 2.96666666666667, 3.2, 3,
3.52, 3.26666666666667, 3.2, 3.45, 3.9, 3.6, 3.35, 3.86666666666667,
3, 3.91666666666667, 3.58333333333333, 4, 3.83333333333333,
3.44444444444444, 3.26666666666667, 3, 3.6, 3.33333333333333,
3.55555555555556, 3.66666666666667, 3.83333333333333, 3.5,
3.41666666666667, 4, 2.33333333333333)), row.names = c(NA,
-48L), class = "data.frame")
df$id=seq(1, nrow(df))
label_data=df
number_of_bar=nrow(label_data)
angle= 90 - 360 * (label_data$id-0.5) /number_of_bar
label_data$hjust<-ifelse( angle < -90, 1, 0)
label_data$angle<-ifelse(angle < -90, angle+180, angle)
ggplot(data=df, aes(x=team, y=value, fill=variable)) +
geom_bar(stat='identity') +
ylim(-100,120) +
theme_minimal() +
theme(
axis.text = element_blank(),
axis.title = element_blank(),
panel.grid = element_blank(),
plot.margin = unit(rep(-1,4), "cm")
) +
coord_polar(start = 0) +
geom_text(data=label_data, aes(x = id, y = 20, label=team, hjust=hjust), color="black", fontface="bold",alpha=0.6, size=2.5, angle= label_data$angle, inherit.aes = FALSE )

Yes, there was an issue how the id was created. We need unique id for every team and also changes in number_of_bar based on unique instances of team.
number_of_bar = length(unique(df$team))
df$id = as.numeric(as.factor(df$team))
label_data = df
angle = 90 - 360 * (label_data$id-0.5) /number_of_bar
label_data$hjust <-ifelse(angle < -90, 1, 0)
label_data$angle <-ifelse(angle < -90, angle+180, angle)
ggplot(data=df, aes(x=team, y=value, fill=variable)) +
geom_bar(stat='identity') +
ylim(-100,120) +
theme_minimal() +
theme(
axis.text = element_blank(),
axis.title = element_blank(),
panel.grid = element_blank(),
plot.margin = unit(rep(-1,4), "cm")
) +
coord_polar(start = 0) +
geom_text(data=label_data, aes(x = id, y = 20, label=team, hjust=hjust),
color="black", fontface="bold",alpha=0.6, size=2.5,
angle= label_data$angle, inherit.aes = FALSE )

Because you have multiple rows per team, you need to rework the code so that the x-values and angles are all based on team, you can't just use the row number:
number_of_bar= length(unique(label_data$team))
angle= 90 - 360 * (as.numeric(str_extract(label_data$team, "\\d+$")) - 0.5) / number_of_bar
label_data$hjust<-ifelse( angle < -90, 1, 0)
label_data$angle<-ifelse(angle < -90, angle+180, angle)
ggplot(data=df, aes(x=team, y=value, fill=variable)) +
geom_bar(stat='identity') +
ylim(-100,120) +
theme_minimal() +
theme(
axis.text = element_blank(),
axis.title = element_blank(),
panel.grid = element_blank(),
plot.margin = unit(rep(-1,4), "cm")
) +
coord_polar(start = 0) +
geom_text(data=label_data, aes(x = team, y = 20, label=team, hjust=hjust), color="black", fontface="bold",alpha=0.6, size=2.5, angle= label_data$angle, inherit.aes = FALSE )

Related

Plot a line and dot plot with a categorical variable on the x-axis, and two variables defining the groups

So I would like to get a plot with two categories on the x-axis, then the color of the lines and data points defined by one variable, and the shape of the points defined by the second variable
effectBaseline <- ggplot(
data = bdataPEV,
aes(x=variable, y=value, group=Electrode, color=subject)) +
geom_line()+
geom_jitter(aes(x=variable,
y = value,
shape = Electrode,
color=subject),
size=2,
show.legend=TRUE,
width = 0.1)+
labs(x = "",
y="PEV (dps)",
title = "Effect of baseline",
subtitle= "PEV values at UCL and T") +
theme_classic() +
theme(axis.title=element_text(size=8,face="bold"),
axis.text.x = element_text(face="bold", size=8, angle=0),
axis.text.y = element_text(face="bold",size=10, angle=90),
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank()) +
geom_hline(yintercept = 0)+
scale_x_discrete(labels=c("no Baseline","with Baseline"))
Example data:
structure(list(subject = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 4L, 4L, 4L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 4L,
4L, 4L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 4L, 4L, 4L), .Label = c("1",
"2", "3", "6"), class = "factor"), Electrode = c("LAN", "SAN",
"PAN", "LAN", "SAN", "PAN", "LAN", "SAN", "PAN", "LAN", "SAN",
"PAN", "LAN", "SAN", "PAN", "LAN", "SAN", "PAN", "LAN", "SAN",
"PAN", "LAN", "SAN", "PAN", "LAN", "SAN", "PAN", "LAN", "SAN",
"PAN", "LAN", "SAN", "PAN", "LAN", "SAN", "PAN"), variable = structure(c(1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,
2L, 2L, 2L), .Label = c("PEVsum_block_noB", "PEVsum_block_B",
"PEVsum_block_B_norm", "PEVsum_block_B_inhibition", "PEVsum_blok_B_inhibition_norm"
), class = "factor"), value = c(26.5655048141819, 24.25, 4.30277563773199,
158.352853610442, 100.585046948683, 26.0372066865141, 147.516666666667,
156.7275, 65.9128571428571, 1.7378211394883, 1.9853826151828,
2.96232650874689, 4.24264068711928, 14, 1, 141.354165131417,
90.2108640907513, 5, 130.96, 137.72, 23.32, 2.4099999998795,
1.86214499960808, 2.96192610446308, -2.82842712474619, 0, -1,
-15.0332963783729, -9.4339811320566, -9.05538513813742, -31.13,
-28.57, -30.27, 0, 0, -0.679999999932)), row.names = c(1L, 2L,
3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L,
17L, 18L, 19L, 20L, 21L, 22L, 23L, 24L, 37L, 38L, 39L, 40L, 41L,
42L, 43L, 44L, 45L, 46L, 47L, 48L), class = "data.frame")
So, I've changed two things in your plot:
I used interaction to group the lines by both the subject and electrode.
I set both lines and points to have the same position adjustment. For more see this question here: How to jitter both geom_line and geom_point by the same magnitude?
pos <- position_dodge(width = 0.1)
ggplot(data = bdataPEV,
aes(
x = variable,
y = value,
color = subject,
shape = Electrode,
group = interaction(subject, Electrode)
)) +
geom_line(position = pos) +
geom_point(
size = 2,
show.legend = TRUE,
position = pos
) +
labs(
x = "",
y = "PEV (dps)",
title = "Effect of baseline",
subtitle = "PEV values at UCL and T"
) +
theme_classic() +
theme(
axis.title = element_text(size = 8, face = "bold"),
axis.text.x = element_text(face = "bold", size = 8, angle = 0),
axis.text.y = element_text(face = "bold", size = 10, angle = 90),
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank()
) +
geom_hline(yintercept = 0) +
scale_x_discrete(labels = c("no Baseline", "with Baseline"))

Labels along x axis disappear when using expand=c(0, 0)

I've a question regarding to the labels of the x-axis. Assume I've the following plot:
p <- ggplot(long_form_q, aes(reihe, variable)) + geom_tile(aes(fill = value), colour = "white")
pneu <- p + scale_fill_gradient(low = "white",high = "steelblue", limits= c(1,3), breaks=c(1,2,3)) +
geom_text(aes(label=long_form_textq$value)) +
theme(axis.title.x = element_blank(),axis.title.y =element_blank()) +
theme(axis.text.y = element_text(size=18, color = "black"), axis.text.x = element_text(size=14)) +
scale_y_discrete(labels=c(h_3x3.1="3x3", h_3x5.1="3x5", h_3x9.1 ="3x9"), expand=c(0,0))
of the following form:
How can I change the labels of the x-axis to (1,2,3,4,5,6,7,8,9,10) while using expand=c(0,0) for x ? If I'm using
scale_x_discrete(expand=c(0,0))
the labels are vanish
My dput is:
dput(long_form_q)
structure(list(reihe = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L,
10L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 1L, 2L, 3L, 4L,
5L, 6L, 7L, 8L, 9L, 10L), variable = structure(c(1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,
2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("h_3x3.1",
"h_3x5.1", "h_3x9.1"), class = "factor"), value = c(1, 1, 1,
2, 1, 1, 1, 1, 1, 1, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 3, 1,
3, 3, 3, 3, 3, 3)), row.names = c(NA, -30L), .Names = c("reihe",
"variable", "value"), class = "data.frame")
You're plotting continuous data along the x axis, so the correct scale is scale_x_continuous(). The reason the labels are disappearing is because you're erroneously using scale_x_discrete().
pneu <- p + scale_fill_gradient(low = "white",high = "steelblue", limits= c(1,3), breaks=c(1,2,3)) +
geom_text(aes(label=value)) +
theme(axis.title.x = element_blank(),axis.title.y =element_blank()) +
theme(axis.text.y = element_text(size=18, color = "black"), axis.text.x = element_text(size=14)) +
scale_y_discrete(labels=c(h_3x3.1="3x3", h_3x5.1="3x5", h_3x9.1 ="3x9"),
expand=c(0, 0)) +
scale_x_continuous(expand = c(0, 0), breaks = 1:10)
pneu
I didn't have your variable long_form_textq$value, so I used long_form_q$value instead. Note that it is almost always a bad idea to feed data into ggplot via the aes() function. Data should be provided via the data = argument.

Problems with geom_tile and scale_colour_distiller

I want to create a correlation plot using geom_tile(). This is a reproducible chunk of code:
library(ggplot2)
df.m <- structure(list(Trait = structure(c(6L, 5L, 1L, 3L, 2L, 9L, 4L,
10L, 11L, 7L, 8L, 6L, 5L, 1L, 3L, 2L, 9L, 4L, 10L, 11L, 7L, 8L,
6L, 5L, 1L, 3L, 2L, 9L, 4L, 10L, 11L, 7L, 8L), .Label = c("R1",
"R2", "R3", "R4", "R5",
"R6", "R7", "R8",
"R9", "R10",
"R11"), class = "factor"), Variable = structure(c(3L,
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 2L, 2L, 2L, 2L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L
), .Label = c("C1", "C2", "C3"), class = "factor"),
value = c(0.967444360256195, 0.937379062175751, 0.647411823272705,
0.512605130672455, 0.50750744342804, 0.508640229701996, 0.508640229701996,
0.503542542457581, 0.442936152219772, 0.510905921459198,
0.504675328731537, NA, 0.834005177021027, 0.667642116546631,
0.579914391040802, 0.579344689846039, 0.536050498485565,
0.532062888145447, 0.52408766746521, 0.520099997520447, 0.504719197750092,
0.450031787157059, NA, NA, 0.571457028388977, 0.451690584421158,
0.354736804962158, 0.46138596534729, 0.477354824542999, 0.447128057479858,
0.287439465522766, 0.498456537723541, 0.508722245693207)), .Names = c("Trait",
"Variable", "value"), row.names = c(NA, -33L), class = "data.frame")
p <- ggplot(na.omit(df.m)) + aes(x = Variable, y = Trait, fill = value) +
geom_tile(colour = "white", size = 0.75) +
scale_colour_distiller(limits = c(-1, 1), direction = -1, palette = "RdBu", name = "Coefficient") +
scale_size(range = c(0,20), name = title, guide = "none") +
geom_text(data = df.m, aes(x = Variable, y = Trait, label = sprintf("%.2f", value)), size = 4, inherit.aes = FALSE) +
theme(plot.title = element_text(size = 20), axis.text.y = element_text(size = 10),
axis.text.x = element_text(size = 10, angle = 90, hjust = 1, vjust = 0.5),
legend.position = "bottom", legend.margin = unit(1.0, "cm"),
legend.text = element_text(size = 8), legend.title = element_text(size = 10),
legend.key.size = unit(1.0, "cm"),
panel.background = element_rect(fill = "white")) +
xlab("\nVariables 1") + ylab("Variables 2\n")
plot(p)
However, the tiles are filled with their own color gradient scale and not with the one defined bye scale_colour_distiller(). Moreover, both key legends appear in the plot:
I just want the tiles to be colored according to the gradient defined by the scale_colour_distiller(). How can I do that? From where geom_plot() is sucking the color scale?
Thanks in advance!
You need to use scale_fill_distiller since you are mapping value to the fill aesthetic and not to the color aesthetic.

scaling yaxix based on data on each panel using facet_grid

t <- structure(list(X = 1:30, Country = structure(c(3L, 1L, 3L, 1L,
3L, 1L, 3L, 1L, 3L, 1L, 3L, 1L, 3L, 1L, 3L, 1L, 3L, 1L, 2L, 2L,
3L, 1L, 3L, 1L, 3L, 1L, 2L, 3L, 1L, 3L), .Label = c("China",
"Germany", "USA"), class = "factor"), Industry = structure(c(3L,
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L,
3L, 3L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("Agriculture",
"IT", "Manufacturing"), class = "factor"), Date = structure(c(15393,
15393, 15394, 15394, 15397, 15397, 15398, 15398, 15399, 15399,
15400, 15400, 15401, 15401, 15404, 15404, 15405, 15405, 15405,
15405, 15406, 15406, 15407, 15407, 15408, 15408, 15408, 15411,
15411, 15412), class = "Date"), count = c(4L, 1L, 5L, 1L, 4L,
1L, 4L, 1L, 8L, 1L, 7L, 1L, 4L, 1L, 4L, 1L, 9L, 1L, 4L, 3L, 4L,
1L, 4L, 1L, 9L, 1L, 2L, 7L, 1L, 4L)), .Names = c("X", "Country",
"Industry", "Date", "count"), row.names = c(NA, 30L), class = "data.frame")
I need to have yaxis scale to be proportionate to the data in that panel. When I do this:
# install.packages("ggplot2", dependencies = TRUE)
# install.packages("scales", dependencies = TRUE)
require(ggplot2)
require(scales)
p1 <- ggplot(t, aes(Date, count)) +
geom_bar(aes(fill=Industry), stat="identity", position="stack") +
geom_smooth(method="lm", se=T, size=0.5, colour="yellow") +
xlab("Date") + ylab("Number of Input") +
facet_grid(Industry~Country, scale="free", margins=T) +
theme(legend.position = 'bottom', legend.direction = 'horizontal', legend.title = element_blank(), legend.text = element_text(size=10, face = 'bold')) +theme(axis.title.x = element_text(face="bold", colour="white", size=12), axis.text.x = element_text(angle=90, face="bold", size=10),axis.title.y = element_text(face="bold", colour="white", angle=90, size=10), axis.text.y=element_text(size=10, face="bold"),legend.text = element_text(size=10, face = 'bold'), legend.title = element_blank()) +scale_x_date(breaks = "3 month", minor_breaks = "1 week", labels=date_format("%b-%y"))+ theme(strip.text.x = element_text(size=10, face="bold", colour="navyblue"), strip.background = element_rect(colour="blue", fill="white"))+ ggtitle("Number of Monthly Breaches")+
theme(plot.title=element_text(size=13, colour="white", face="bold")) + ylim(0, max(t$count))
yaxis limit is the same for all panels, I tried this
scales=free_y
it does not seem to be working. Any idea how to tackle this issue?
guy, you might have tried scales="free_y" but you have a + ylim(0, max(t$count) at the end of your code. Remove that and see what happens ;)
The answer above is good. I want just to structure your code because it looks really hard to maintain. I would not mix the plot and the theme statements.
The plot alone :
p1 <- ggplot(dat, aes(Date, count)) +
geom_bar(aes(fill=Industry), stat="identity", position="stack") +
geom_smooth(method="lm", se=T, size=0.5, colour="yellow") +
facet_grid(Industry~Country, scales="free_y", margins=T) +
scale_x_date(breaks = "3 month", minor_breaks = "1 week",
labels=date_format("%b-%y"))
Then theme
mytheme <- theme(legend.position = 'bottom', legend.direction = 'horizontal',
legend.title = element_blank(),
legend.text = element_text(size=10, face = 'bold')) +
theme(axis.title.x = element_text(face="bold", colour="white", size=12),
axis.text.x = element_text(angle=90, face="bold", size=10),
axis.title.y = element_text(face="bold",
colour="white",
angle=90,
size=10),
axis.text.y=element_text(size=10, face="bold"),
legend.text = element_text(size=10, face = 'bold'),
legend.title = element_blank()) +
theme(strip.text.x = element_text(size=10,
face="bold", colour="navyblue"),
strip.background = element_rect(colour="blue", fill="white"))+
theme(plot.title=element_text(size=13, colour="white", face="bold"))
p1 + mytheme

Bipartite network graph with ggplot2

I have the following data frame:
structure(list(X1 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L,
4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 6L, 6L, 6L
), .Label = c("1", "2", "3", "4", "5", "6"), class = "factor"),
X2 = structure(c(1L, 6L, 8L, 10L, 12L, 13L, 3L, 4L, 1L, 6L,
7L, 9L, 10L, 12L, 13L, 3L, 4L, 5L, 10L, 12L, 13L, 4L, 1L,
6L, 12L, 13L, 3L, 1L, 6L, 7L, 8L, 10L, 11L, 12L, 13L, 2L,
3L, 11L, 12L, 13L), .Label = c("I1", "I10", "I11", "I12",
"I13", "I2", "I3", "I4", "I5", "I6", "I7", "I8", "I9"), class = "factor")), .Names = c("X1",
"X2"), row.names = c(NA, -40L), class = "data.frame")
Where in X1 is the person number and in X2 the group to which the person belongs to. One person can be in different groups.
Now I want to draw a line from each person to each group he belongs to. With plot() I solved it this way:
plot(0, xlim=c(0,1), ylim=c(0,1), type="n", axes=FALSE, xlab="", ylab="")
factor.to.int <- function(f) {
(as.integer(f) - 1) / (length(levels(f)) - 1)
}
segments(factor.to.int(data$X1), 0, factor.to.int(data$X2), 1, col=data$X1)
axis(1, at = seq(0, 1, by = 1 / (length(levels(data$X1)) - 1)), labels = levels(data$X1))
axis(3, at = seq(0, 1, by = 1 / (length(levels(data$X2)) - 1)), labels = levels(data$X2))
The result looks like this:
Now I wondering how I can do this with ggplot2?
Thanks for your help!
A simple ggplot2 version of your graph is possible by using geom_segment() and transforming the data much like you did for the base graphics version. I've also included an arguably more polished version, using some of the more advanced customization options in ggplot2.
# Using ggplot2 version 0.9.2.1
library(ggplot2)
dat$x1_norm = rangeTransform(as.integer(dat$X1))
dat$x2_norm = rangeTransform(as.integer(dat$X2))
dat$y1 = 0
dat$y2 = 1
# Simple version.
p1 = ggplot(dat, aes(x=x1_norm, xend=x2_norm, y=y1, yend=y2, colour=X1)) +
geom_segment(size=1.2) +
scale_colour_brewer(palette="Set1", name="Person")
ggsave(plot=p1, filename="plot_1.png", height=3.5, width=6)
# Fancy version.
# Create separate data.frames to manually specify axis ticks and axis text.
axis_1 = data.frame(x=rangeTransform(as.integer(unique(dat$X1))),
y=0, label=as.character(unique(dat$X1)))
axis_2 = data.frame(x=rangeTransform(as.integer(unique(dat$X2))),
y=1, label=as.character(unique(dat$X2)))
p2 = ggplot(data=dat) +
theme_bw() +
theme(axis.title=element_blank()) +
theme(axis.text=element_blank()) +
theme(axis.ticks=element_blank()) +
theme(panel.grid=element_blank()) +
geom_segment(aes(x=x1_norm, xend=x2_norm, y=y1, yend=y2, colour=X1),
size=1.2) +
geom_segment(x=0, xend=1, y=0, yend=0, size=0.7) +
geom_segment(x=0, xend=1, y=1, yend=1, size=0.7) +
scale_colour_brewer(palette="Set1", name="Person") +
scale_y_continuous(limits=c(-0.2, 1.2), expand=c(0, 0)) +
geom_segment(data=axis_1, aes(x=x, xend=x, y=y, yend=y-0.025), size=0.7) +
geom_segment(data=axis_2, aes(x=x, xend=x, y=y, yend=y+0.025), size=0.7) +
geom_text(data=axis_1, aes(label=label, x=x, y=y - 0.075)) +
geom_text(data=axis_2, aes(label=label, x=x, y=y + 0.075))
ggsave(plot=p2, filename="plot_2.png", height=3.5, width=6)

Resources