I'm plotting a stacked bar graph and use geom_text to insert the value of each stack. The difficulty I'm facing is that some stacks are very small/narrow, so that the text of two stacks overlap each other and hence is not very readable. I would like to adjust the text positioning in a way that for example the text position alternates between hjust == 1 and hjust == -1 for each stack, so that there will be no overlaps (or any other method that will result in readable text).
Here's an example of what I'm currently doing (a dput of mydf is provided below):
library(ggplot2)
ggplot(mydf, aes(x=variable, y = value, fill = Category)) +
geom_bar(stat="identity") +
geom_text(aes(label = value, y = pos-(value/2)), size = 3)
What I tried so far is:
Using position = position_dodge(width = 0.5) and position = position_jitter(h =0.5, w = 0.5) but none resulted in what I was trying to do.
My first thought was to define hjust = c(1,-1) hoping that it would be recycled and texts would alternate between hjust == 1 and hjust == -1 but it results in the error message:
Error: Incompatible lengths for set aesthetics: size, hjust
I also tried defining size = c(3,3,3,3,3,3,3,3,3), hjust = c(1,-1,1,-1,1,-1,1,-1,1) but this results in the same error message.
I would appreciate some advice on how to achieve this the right way (and I'm open to other suggestions as well).
I couldn't figure out why the dput didn't work (also for me it didn't), so here's the data in readable format:
Category variable value pos maxpos
1 AX WW 47.8 47.8 184.1
2 AY WW 5.6 53.4 184.1
3 AZ WW 15.8 69.2 184.1
4 BX WW 31.4 100.6 184.1
5 BY WW 11.7 112.3 184.1
6 BZ WW 10.7 123.0 184.1
7 CX WW 2.2 125.2 184.1
8 CY WW 21.4 146.6 184.1
9 CZ WW 37.5 184.1 184.1
10 AX SM 39.8 39.8 148.6
11 AY SM 2.9 42.7 148.6
12 AZ SM 13.2 55.9 148.6
13 BX SM 22.7 78.6 148.6
14 BY SM 7.3 85.9 148.6
15 BZ SM 8.9 94.8 148.6
16 CX SM 1.6 96.4 148.6
17 CY SM 17.3 113.7 148.6
18 CZ SM 34.9 148.6 148.6
19 AX AsIs 156.9 156.9 519.0
20 AY AsIs 13.1 170.0 519.0
21 AZ AsIs 70.5 240.5 519.0
22 BX AsIs 72.6 313.1 519.0
23 BY AsIs 30.7 343.8 519.0
24 BZ AsIs 35.6 379.4 519.0
25 CX AsIs 5.2 384.6 519.0
26 CY AsIs 44.8 429.4 519.0
27 CZ AsIs 89.6 519.0 519.0
By creating a hjust variable, you can achieve the desired result. The code:
mydf$hj <- rep(c(1,0,-1), length.out=27)
ggplot(mydf, aes(x=variable, y=value, fill=Category)) +
geom_bar(stat="identity") +
geom_text(aes(label=value, y=pos-(value/2), hjust=hj), size=4)
which gives:
A slightly alternative solution proposed by #konvas:
ggplot(mydf, aes(x=variable, y=value, fill=Category)) +
geom_bar(stat="identity") +
geom_text(aes(label=value, y=pos-(value/2), hjust=rep(c(1,0,-1), length.out=length(value))), size=4)
Related
I have the next code, where I have negative positive and negative values and I want to put the positive values above the edge of bar, and negative values below the edge of the bar. I want to know too how to change the y axes (limites), changes the order of "Flujo" and how to change background graph.
tabla <-
Flujo Mes Valor
1 Qns Septiembre 79.4
2 Qnl Septiembre -97.5
3 Qh Septiembre -3.1
4 Qe Septiembre -11.3
5 Qr Septiembre 0.5
6 Qg Septiembre 16.5
7 Qm Septiembre 15.5
8 Qns Octubre 79.1
9 Qnl Octubre -87.8
10 Qh Octubre -0.8
11 Qe Octubre -1.7
12 Qr Octubre 0.0
13 Qg Octubre 36.0
14 Qm Octubre -57.9
tabla<-data.frame("Flujo"=c("Qns","Qnl","Qh","Qe","Qr","Qg","Qm","Qns","Qnl","Qh","Qe","Qr","Qg","Qm"),
"Mes"= rbind(array(" Septiembre", dim=c(7,1)) , array("Octubre", dim=c(7,1))) ,
"Valor"=round(c(s1$Qns,s1$Qnl,s1$Qh,s1$Qe,s1$Qr,s1$Qg,s1$Qm,s2$Qns,s2$Qnl,s2$Qh,s2$Qe,s2$Qr,s2$Qg,s2$Qm),digits=1))
colors <-c("Qns"="red","Qnl"="blue","Qh"="deeppink","Qe"="darkgoldenrod1","Qr"="darkblue","Qg"="green","Qm"="brown")
fig31 <- ggplot(data=tabla, aes(x=Mes, y=Valor,fill=Flujo)) +
geom_bar(stat="identity", color="black", position=position_dodge())+
theme_minimal()+
geom_text(aes(label=Valor),position=position_dodge(width=0.9),size=4, vjust=1.5)+
scale_fill_manual(values = colors) +
theme_light()
fig31
Here is one way you could do: I changed geom_bar with geom_col anc put an ifelse in geom_text(). Here you can define the position 0,-1,1.5` of the numbers.
fig31 <- ggplot(tabla, aes(Mes, Valor, fill=Flujo)) +
geom_col(position = position_dodge()) +
geom_text(aes(label = paste(Valor)),
position=position_dodge(width=0.9),size=3,
vjust = ifelse(tabla$Valor >= 0, -1, 1.5)) +
scale_fill_manual(values = colors) +
theme_light()
fig31
I am an R beginner user and I face the following problem. I have the following data frame:
distance speed
1 61.0 36.4
2 51.4 35.3
3 42.2 34.2
4 33.4 32.8
5 24.9 31.3
6 17.5 28.4
7 11.5 24.1
8 7.1 19.4
9 3.3 16.9
10 0.5 15.5
11 4.4 15.1
12 8.5 15.5
13 13.1 17.3
14 18.8 20.5
15 25.7 24.1
16 33.3 26.3
17 41.0 27.0
18 48.7 27.7
19 56.6 28.4
20 64.8 29.2
21 73.6 31.7
22 83.3 34.2
23 93.4 35.3
The column distance represents the distance of a following object over a specific point and the column speed the object's speed. As you can see the object is getting closer to the point and then it is getting away. I am trying to make its speed profile. I tried the following code but it didn't give me the plot I want (because I want to show how its speed is changing when the moving object moves closer and past the reference point)
ggplot(speedprofile, aes(x = distance, y = speed)) + #speedprofile is the data frame
geom_line(color = "red") +
geom_smooth() +
geom_vline(xintercept = 0) # the vline is the reference line
The plot is the following:
Then, I tried to set the first 10 distances as negative manually which are prior to zero (0). So I get a plot closer to that I want:
But there is a problem. The distance can't be defined as negative.
To sum up, the expected plot is the following (and I am sorry for the quality).
Do you have any ideas on how to solve this?
Thank you in advance!
You can do something like this to auto-compute the change point (to know when the distance should be negative) and then set the axis labels to be positive.
Your data (in case anyone needs it to answer):
read.table(text="distance speed
61.0 36.4
51.4 35.3
42.2 34.2
33.4 32.8
24.9 31.3
17.5 28.4
11.5 24.1
7.1 19.4
3.3 16.9
0.5 15.5
4.4 15.1
8.5 15.5
13.1 17.3
18.8 20.5
25.7 24.1
33.3 26.3
41.0 27.0
48.7 27.7
56.6 28.4
64.8 29.2
73.6 31.7
83.3 34.2
93.4 35.3", stringsAsFactors=FALSE, header=TRUE) -> speed_profile
Now, compute the "real" distance (negative for approaching, positive for receding):
speed_profile$real_distance <- c(-1, sign(diff(speed_profile$distance))) * speed_profile$distance
Now, compute the X axis breaks ahead of time:
breaks <- scales::pretty_breaks(10)(range(speed_profile$real_distance))
ggplot(speed_profile, aes(real_distance, speed)) +
geom_smooth(linetype = "dashed") +
geom_line(color = "#cb181d", size = 1) +
scale_x_continuous(
name = "distance",
breaks = breaks,
labels = abs(breaks) # make all the labels for the axis positive
)
Provided fonts are working well on your system you could even do:
labels <- abs(breaks)
labels[(!breaks == 0)] <- sprintf("%s\n→", labels[(!breaks == 0)])
ggplot(speed_profile, aes(real_distance, speed)) +
geom_smooth(linetype = "dashed") +
geom_line(color = "#cb181d", size = 1) +
scale_x_continuous(
name = "distance",
breaks = breaks,
labels = labels,
)
I have created a dummy dataframe representative of my data-
SQ AgeGroup Prop LCI UCI
2010-1 0 to 18 4.3 4.2 4.4
2010-1 19 to 25 5.6 5.3 5.6
2010-1 26 and over 7.8 7.6 7.9
2010-2 0 to 18 4.1 3.9 4.2
2010-2 19 to 25 5.8 5.6 5.9
2010-2 26 and over 8.1 7.9 8.3
2010-3 0 to 18 4.2 4 4.4
2010-3 19 to 25 5.5 5.2 5.6
2010-3 26 and over 7.6 7.4 7.7
2010-4 0 to 18 3.9 3.6 4.1
2010-4 19 to 25 5.2 5 5.4
2010-4 26 and over 7.4 7.2 7.6
2011-1 0 to 18 4.3 4.1 4.5
2011-1 19 to 25 5.7 5.5 5.8
2011-1 26 and over 8.2 8 8.3
2011-2 0 to 18 4.1 4 4.5
2011-2 19 to 25 5.7 5.5 5.9
2011-2 26 and over 8.2 8 8.4
2011-3 0 to 18 4.4 4.2 4.6
2011-3 19 to 25 5.7 5.5 7.9
2011-3 26 and over 8.2 8 8.4
which creates an image that looks like this-
I have used the following code-
library(readxl)
library(dplyr)
library(epitools)
library(gtools)
library(reshape2)
library(binom)
library(pivottabler)
library(readxl)
library(phecharts)
library(ggplot2)
library(RODBC)
rm(list=ls())
df<-read_xlsx("Dummydata.xlsx")
pd<-position_dodge(width=0.3)
limits <- aes(ymax =df$UCI , ymin = df$LCI)
p<-ggplot(df, aes(x = SQ, y =Prop, group=AgeGroup, colour= AgeGroup)) +
geom_line(position=pd)+
geom_point(size=2.0, position=pd)+
geom_errorbar(limits, width = 0.55, size=0.4, position= pd)+
labs(
y = "Percentage",
x = "Study Quarter")
p<-p +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))+
scale_y_continuous(name="Percentage",breaks=c(0,2,4,6,8,10),limits=c(0,10))+#limits need to change with every pot
scale_fill_manual(values = pal)+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1,size=16))+
theme(axis.text.y=element_text(size=16))+
theme(legend.text = element_text(size=18))+
theme(legend.title=element_text(size=16))+
theme(legend.title=element_blank())+
theme(legend.position="bottom")+
theme(axis.title = element_text(size=22))
p + geom_vline(xintercept = c(2,4,6), linetype="dotted",
color = "black", size=1.0, show.legend = TRUE)
However, what I want is that the three geom lines should have a lable (L1, L2 and L3) at the top of each of these lines and a separate legend at the bottom where I can add what these lines stand for. Something like this-
L1: Launch of x
L2: Launch of y
L3: Launch of z
Can someone please help with this?
My dataset:
Taxa dn dc
Cha 10.2 -20.4
Cha 10.7 -19.7
Cha 4.9 -21.0
Cha 5.4 -20.6
Cha 8.6 -21.2
Cha 8.0 -20.9
Cha 8.1 -21.3
Cha 6.9 -21.1
Cha 8.5 -21.1
Cha 9.1 -20.8
Hyd 6.6 -19.2
Hyd 10.2 -17.0
Hyd 9.7 -18.2
Hyd 8.1 -16.5
Hyd 8.8 -15.8
Hyd 8.7 -15.8
Hyd 7.6 -18.3
Hyd 8.9 -16.0
Hyd 8.4 -17.5
Hyd 9.8 -18.8
Hyd 8.3 -18.4
Scy 9.4 -20.1
Scy 9.1 -20.0
Scy 7.8 -20.2
Scy 9.1 -17.6
Scy 8.2 -19.8
Scy 9.4 -19.2
Scy 9.0 -20.1
Sip 5.7 -15.2
Sip 6.2 -18.6
Sip 5.6 -18.0
Sip 8.6 -17.6
Sip 4.8 -16.9
Sip 5.2 -15.4
Sip 1.9 -18.4
The code I use is:
library(ggplot2)
ggplot(mydata, aes(x=dC, y=dN, colour=Taxa, shape=Taxa))+
geom_point(size=2, alpha=0.5)+
geom_polygon(aes(fill=Taxa, group=Taxa))+
theme(legend.position = "none")
I would like to plot the polygon group with "Taxa" in my data. However, it looks like the polygon connects each point.
What I want is like this one. How should I edit my codes?
To connect outer points in group and encircle ones that are within the group use geom_encircle function from ggalt package.
library(ggplot2)
library(ggalt)
ggplot(mydata, aes(dc, dn)) +
geom_point(aes(color = Taxa)) +
geom_encircle(aes(fill = Taxa), s_shape = 1, expand = 0,
alpha = 0.2, color = "black", show.legend = FALSE)
Use s_shape = 1 and expand = 0 to connect outer points, otherwise it will encircle with margins.
You can also calculate the convex hulls, them plot them down:
library(ggplot2)
library(plyr)
# some fake data:
mydata <- data.frame(Taxa = c('Cha','Cha','Cha','Cha','Cha','Cha','Hyd','Hyd','Hyd','Hyd','Hyd','Hyd'),
dn = c(10.2,10.7,4.9,5.4,8.6,8.0, 6.6,10.2,9.7,8.1,8.8,8.7),
dc =c(-20.4,-19.7,-21.0,-20.6,-21.2,-20.9,-19.2,-17.0,-18.2,-16.5,-15.8,-15.8))
# calculate convex hulls:
chulls <- ddply(mydata, .(Taxa), function(mydata) mydata[chull(mydata$dn, mydata$dc), ])
# plot them:
ggplot(data=mydata, aes(x=dn, y=dc, color=Taxa)) + geom_point() +
geom_polygon(data=chulls, aes(x=dn, y=dc, fill=Taxa, alpha=0.2))
Nice source here.
I have found many topics about the legend title with ggplot2 but after a couple of hours I have not been able to handle my situation.
Here is the dataset:
> dat
FACTOR1 FACTOR2 lsmean lower.CL upper.CL
1 A aa 26.2 25.6 26.8
2 B aa 24.8 23.9 25.7
3 A bb 26.0 25.2 26.7
4 B bb 24.9 23.9 25.9
5 A cc 24.4 23.9 24.8
6 B cc 23.9 22.9 25.0
7 A dd 24.9 24.3 25.6
8 B dd 23.2 22.3 24.0
And the graphic of interest:
gp0 <- ggplot(dat, aes(x=FACTOR2, y=lsmean, group=FACTOR1, colour=FACTOR1))
( gp1 <- gp0 + geom_line(aes(linetype=FACTOR1), size=.6) +
geom_point(aes(shape=FACTOR1), size=3) +
geom_errorbar(aes(ymax=upper.CL, ymin=lower.CL), width=.1) +
geom_errorbar(aes(ymax=upper.CL, ymin=lower.CL), width=.1) )
If I use scale_colour_manual() to change the legend title then I get an unexpected additional legend:
gp1 + scale_colour_manual("NEW TITLE",values=c("red","blue"))
I suppress this additional legend with scale_"aes"_manual("guide=none", values=...) but I don't understand how to control the parameters (the style of points and lines):
gp1 + scale_colour_manual("NEW TITLE",values=c("red","blue")) +
scale_shape_manual(guide = 'none', values=c(1,2)) +
scale_linetype_manual(guide = 'none', values=c(1,3))
Please how to reproduce the first plot with and only with a new legend title ?
You have to set the same title for all aes() attributes you have used, for example, using function labs().
gp1 + scale_colour_manual(values=c("red","blue"))+
labs(colour="NEW TITLE",linetype="NEW TITLE",shape="NEW TITLE")