I'd like to place some text in my scatterplot, which I made with ggplot like you can see in the top left corner of the plot:
The text is now showing "Text" and "Variable", but should show more "Text" after the "Variable" and should be left aligned:
The requirements are:
It must have the format "Text" "Variable" "Text"
I need two or three rows
The rows should be left-aligned
What I did is using this code, but it might be not adequate for my intentions:
p1 + annotate(geom="text", x=1, y = 15, col="black",
label=paste("atop(' Mean diff = '*",bias,",'SD of diff = '*",sd,")"), parse=T)
Related
Is there a way to vertical align the symbols in a legend relative to the first line of the corresponding text?
plot(table(iris$species))
legend('right',c('A','B','long\ntext'), fill = colors(3))
The labels A and B are vertically aligned to the corresponding symbols, but the symbol corresponding to the the third label (long text with a line-break between the words) is aligned to the middle of this label.
I would prefer if the symbol would be aligned to the first line of the label (i.e. long).
The easiest way is to put a blank line before the text. That way, the first line of text will be aligned with the box:
pie(table(iris$Species), col = palette.colors(3, "Pastel 1"), cex = 2)
legend('right',c('A','B',' \nlong\ntext'), fill = palette.colors(3, "Pastel 1"),
cex = 2, box.lty = 0, y.intersp = 0)
iris <- iris
ggplot(iris, aes(x=Species, fill=Species)) +
geom_bar() +
scale_fill_manual(values=colors(3), labels=c('A', 'B', 'long\ntext')) +
theme(legend.position="right", legend.justification=0.5)
I have two issue on this plot. I want to make the bars wider (and less spacing between the groups) and I want each group of bars to be centered to each x factor values.
I have a continuous variable on the y-axis and a factor value on the x-axis. I have three groups for each factor.
Here is an example of my issue with the Iris data:
d <- iris
ggplot(d) +
geom_col(aes(x=as.factor(Sepal.Length), y=Petal.Width, fill=as.factor(Species)),position = position_dodge(preserve = "single"), width=1) +
theme(axis.text.x = element_text(angle = 90).
This gets you something probably closer to what you're looking for (I assume d in your example is iris):
ggplot(iris) +
geom_col(
aes(
x=as.factor(Sepal.Length), y=Petal.Width, fill=Species
),
position = position_dodge(0.5),
width=0.5) +
theme(axis.text.x = element_text(angle = 90, vjust=0.5))
Now, for the explanation of what I changed and why:
Text Positioning on X-axis. You used element_text(angle=90) to change the direction of the text. This is correct, but it only changes the angle and not the positioning/alignments. By default, horizontal text is vertically aligned to be "at the top". If you run the code above and use vjust=1 in place of vjust=0.5, you'll see it goes back to the way it appears for you, with the tick marks being aligned to the "top" of the value on the x axis text.
as.factor(Species) No need to declare Species a factor. Run str(iris) and you'll see that iris$Species is already a factor. Doesn't really change anything to the result except messes with the title of the legend.
Position_dodge width and width. This one is best explained by you messing with the values in the two terms position_dodge(0.5) and width=0.5. Play with it yourself and you'll see what they each do, but here's the general explanation:
Total column width for each position on the x-axis is determined by width=0.5 that is the argument for geom_col(). So, for every Sepal.Length factor in this graph, it means that "0.5" is used as the total width of the column (or columns) that are in that space. "1.0" would mean "I want all columns to touch each other" and something like "0.2" means "I want skinny columns". "0" means... I don't want columns - give them a width of zero!
The width of each "sub-column" (each Species column for each Sepal.Length in this example) is controlled by the position_dodge(width=0.5) term. 0.5 represents "split this in half and have the columns touch each other exactly". Higher values will split them apart and lower values will squish them together, where 0 means they are on top of one another. Making the value really large, you get sub-columns running into neighboring columns...
Again - play around with those terms and you should get how they work together.
Maybe an another solution is to use position_dodge2 that will center each bar to the center of x values:
ggplot(iris, aes(x = as.factor(Sepal.Length), y = Petal.Width, fill = Species))+
geom_col(position = position_dodge2(preserve = "single", width = 1))+
theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5))
I am writing some text on my plot, which works perfectly fine. Now I realized that if I put the text further down the y-axis, the plot space somehow becomes larger. This is not what I want. The following 2 plots illustrate the issue. The first one puts the text at y = 0, whereas the second one puts it at y = the min-0.25, so roughly where the plot space begins vertically. Is it possible to keep the plot space as in the first plot, but still to write at the bottom? If there is no intended way to adjust that, I would also be happy with a workaround.
set.seed(12)
test <- data.table(x = rnorm(29*2),var=c(rep("x1",29),rep("x2",29)),
time=rep(seq(as.Date("1983/12/31"),as.Date("2011/12/31"), "year"),2))
library(ggplot2);library(scales)
ggplot(data=test,aes(x=time, y=x, colour=var)) +
geom_line() + scale_x_date(date_labels="%Y",date_breaks = "3 years") +
geom_text(aes(x=as.Date("1988-04-30"), label="Text which does not increases space", y=0,
fontface="plain"), angle=60, colour="black",vjust=0,hjust=0,size = 4)
ggplot(data=test,aes(x=time, y=x, colour=var)) +
geom_line() + scale_x_date(date_labels="%Y",date_breaks = "3 years") +
geom_text(aes(x=as.Date("1988-04-30"), label="Text which increases space", y=min(test[,x])-0.25,
fontface="plain"), angle=60, colour="black",vjust=0,hjust=0,size = 4)
As any other geom, geom_text expands the plotting area in cases like this. Then it's necessary to manually restrict the y axis with ylim(range(test$x)). However, that's not enough, as then the text wouldn't be fully visible and, as a result, ggplot completely drops it. To fix this, we need clip = "off". Thus, adding
coord_cartesian(clip = "off", ylim = range(test$x))
gives
where now axes are unchanged.
I have a facet plot in R and I want to give a subtitle to the different columns and the different rows of the plot.
I created an example based on the mpg data.
library(ggplot2)
p <- ggplot(mpg, aes(displ, cty)) + geom_point()
p + facet_grid(drv ~ cyl) +
scale_y_continuous("cty",
sec.axis = sec_axis(~., breaks=NULL, name = "drv")) +
ggtitle("plot from mpg", subtitle="cyl")
This already does what I want. The label on the bottom describes the x-axis on each of the little plots. The label on the top describes what the 4 columns represent. The label on the left describes the y-axis on the little plots and the label on the right describes the rows of the plot.
However, I kind of cheated. The label on the top is actually a subtitle of the plot and the label on the right is created through a secondary axis. I had to put breaks=NULL to hide the secondary axis and just display its name. This also creates lots of warning messages.
Is there a proper way with facet_grid to do what I want?
Edit: I noticed that my code example was incomplete and not functional. I corrected it, hopefully it works now.
So I have a bar chart to make, and a log plot for y axis is warranted because of the data range. So the problem is I have the value of 0.5, which in log10 is -0.3.
Since the bar goes into negative, the "top" of the bar, which is used for placing the labels is actually the "bottom" and so my text label is "just above" the bottom, which means in the middle of the bar.
I figure I am probably not the first person with this issue, but searching for related fixes has not helped. Most notably, I tried using dodge, but this does not change that the "top" of the bar is really the "bottom".
So two questions:
Can I fix this label mishap?
This is just ugly: can I move the x axis up to y=1 to give more context to the negative value without moving the x axis labels?
.
alpha=c('A','B','C','D')
value=c(0.5,10,40,1100)
table<-as.data.frame(alpha)
table<-cbind(table, value)
library(ggplot2)
graph <- ggplot(table, aes(x=alpha)) +
geom_bar(stat="identity",aes(y=value),width=0.5) +
geom_text(aes(y=value,label=value),vjust=-0.5) +
scale_y_continuous(trans="log10",limits=c(0.5,1400))
graph + theme_classic()
A little trick modifying the y coordinate of the data labels (use ifelse() to set the value of y to 1 if the value is less than one). As for the axis, simply hide the X axis (setting it to element_blank()) and draw a new horizontal line:
graph <- ggplot(table, aes(x=alpha)) +
geom_bar(stat="identity",aes(y=value),width=0.5) +
# Modify the placing of the label using 'ifelse()':
geom_text(aes(y=ifelse(value < 1, 1, value),label=value),vjust=-0.5) +
scale_y_continuous(trans="log10",limits=c(0.5,1400)) +
theme_classic() +
# Hide the X axis:
theme(axis.line.x = element_blank()) +
# Draw the new axis
geom_hline()
print(graph)
The output: