I have a faceted ggplot2 scatterplot, and would like to print summary statistics about the linear regression on each facet, as has been done here and here. Unlike those examples, I am using scales="free", and the ranges of the data in each facet are quite different, but I would like the summary statistics to show up in the same relative position in each facet (e.g. top right corner, or whatever). How can I specify to geom_text or annotate that the label should appear in the same position relative to the panel?
Where I am right now:
# Fake data
set.seed(2112)
x <- c(1:10, 6:15)
y <- x + c(runif(10), runif(10)*10)
l <- gl(2, 10)
d <- data.frame(x=x, y=y, l=l)
# Calculate a summary statistic (here, the r-squared) in a separate data frame
r_df <- ddply(d, .(l), summarise, rsq=round(summary(lm(y~x))$r.squared, 2))
# Use geom_text and a separate data frame to print the summary statistic
ggplot(d, aes(x=x, y=y)) +
geom_text(data=r_df, aes(x=8, y=8, label=paste("rsq=", rsq)))+
geom_point() +
facet_wrap(~l, scales="free")
I would like, instead, to have ggplot automatically position the text in the same relative position in each facet.
If you want to place them relative to the corners, you can achieve that by specifying an x or y position of Inf or -Inf:
ggplot(d, aes(x=x, y=y)) +
geom_text(data=r_df, aes(label=paste("rsq=", rsq)),
x=-Inf, y=Inf, hjust=-0.2, vjust=1.2)+
geom_point() +
facet_wrap(~l, scales="free")
I also adjusted hjust and vjust so the label was not in the exact corner of the graph by pushed away from it a bit.
Related
I have a data frame with three continuous variables (x,y,z). I want a column plot in which x defines the x-axis position of the columns, y defines the length of the columns, and the column colors (function of y) are defined by z. The test code below shows the set up.
`require(ggplot2)
require(viridis)
# Create a dummy data frame
x <- c(rep(0.0, 5),rep(0.5,10),rep(1.0,15))
y <- c(seq(0.0,-5,length.out=5),
seq(0.0,-10,length.out=10),
seq(0.0,-15,length.out=15))
z <- c(seq(10,0,length.out=5),
seq(8,0,length.out=10),
seq(6,0,length.out=15))
df <- data.frame(x=x, y=y, z=z)
pbase <- ggplot(df, aes(x=x, y=y, fill=z))
ptest <- pbase + geom_col(width=0.5, position="identity") +
scale_fill_viridis(option="turbo",
limits = c(0,10),
breaks=seq(0,10,2.5),
labels=c("0","2.5","5.0","7.5","10.0"))
print(ptest)`
The legend has the correct colors but the columns do not. Perhaps this is not the correct way to do this type of plot. I tried using geom_bar() which creates a bars with the correct colors but the y-values are incorrect.
It looks like you have 3 X values that each appear 5, 10, or 15 times. Do you want the bars to be overlaid on top of one another, as they are now? If you add an alpha = 0.5 to the geom_col call you'll see the overlapping bars.
Alternatively, you might use dodging to show the bars next to one another instead of on top of one another.
ggplot(df, aes(x=x, y=y, fill=z, group = z)) +
geom_col(width=0.5, position=position_dodge()) +
scale_fill_viridis_c(option="turbo", # added with ggplot 3.x in 2018
limits = c(0,10),
breaks=seq(0,10,2.5),
labels=c("0","2.5","5.0","7.5","10.0"))
Or you might plot the data in order of y so that the smaller bars appear on top, visibly:
ggplot(dplyr::arrange(df,y), aes(x=x, y=y, fill=z))+
geom_col(width=0.5, position="identity") +
scale_fill_viridis_c(option="turbo",
limits = c(0,10),
breaks=seq(0,10,2.5),
labels=c("0","2.5","5.0","7.5","10.0"))
I solved this by using geom_tile() in place of geom_col().
I am plotting a series of point that are grouped by two factors. I would like to add lines within one group across the other and within the x value (across the position-dodge distance) to visually highlight trends within the data.
geom_line(), geom_segment(), and geom_path() all seem to plot only to the actual x value rather than the position-dodge place of the data points. Is there a way to add a line connecting points within the x value?
Here is a structurally analogous sample:
# Create a sample data set
d <- data.frame(expand.grid(x=letters[1:3],
g1=factor(1:2),
g2=factor(1:2)),
y=rnorm(12))
# Load ggplot2
library(ggplot2)
# Define position dodge
pd <- position_dodge(0.75)
# Define the plot
p <- ggplot(d, aes(x=x, y=y, colour=g1, group=interaction(g1,g2))) +
geom_point(aes(shape = factor(g2)), position=pd) +
geom_line()
# Look at the figure
p
# How to plot the line instead across g1, within g2, and within x?
Simply trying to close this question (#Axeman please feel free to take over my answer).
p <- ggplot(d, aes(x=x, y=y, colour=g1, group=interaction(g1,g2))) +
geom_point(aes(shape = factor(g2)), position=pd) +
geom_line(position = pd)
# Look at the figure
p
I would like to create a function that produce a ggplot graph.
data1 <- data.table(x=1:5, y=1:5, z=c(1,2,1,2,1))
data2 <- data.table(x=1:5, y=11:15, z=c(1,2,1,2,1))
myfun <- function(data){
ggplot(data, aes(x=x, y=y)) +
geom_point() +
geom_text(aes(label=y), y=3) +
facet_grid(z~.)
}
myfun(data2)
It is supposed to label some text on the graph. However, without knowing the data in advance I am unable to adjust the positions of text vertically manually. Especially I don't want the label to move positions with data: I want it always stays at about 1/4 vertically of the plots. (top-mid)
How can I do that?
Is there a function that returns the y.limit.up and y.limit.bottom then I can assign y = (y.limit.up + y.limit.bottm) / 2 or something.
Setting either x or y position in geom_text(...) relative to the plot scale in a facet is actually a pretty big problem. #agstudy's solution works if the y scale is the same for all facets. This is because, in calculating range (or max, or min, etc), ggplot uses the unsubsetted data, not the data subsetted for the appropriate facet (see this question).
You can achieve what you want using auxiliary tables, though.
data1 <- data.table(x=1:5, y=1:5, z=c(1,2,1,2,1))
data2 <- data.table(x=1:5, y=11:15, z=c(1,2,1,2,1))
myfun <- function(data){
label.pos <- data[,ypos:=min(y)+0.75*diff(range(y)),by=z] # 75% to the top...
ggplot(data, aes(x=x, y=y)) +
geom_point() +
# geom_text(aes(label=y), y=3) +
geom_text(data=label.pos, aes(y=ypos, label=y)) +
facet_grid(z~., scales="free") # note scales = "free"
}
myfun(data2)
Produces this.
If you want scales="fixed", then #agstudy's solution is the way to go.
You can do this for example:
ggplot(data2, aes(x=x)) +
geom_point(aes(y=y)) +
geom_text(aes(label=y, y=mean(range(y)))) +
facet_grid(z~.)
Or fix y limits manually:
scale_y_continuous(limits = c(10, 15))
#user890739 :
with geom_density you can estimate an ypos variable like this :
data<-dplyr::mutate(group_by(data, z), ypos=max(density(y)$y)*.75*nrow(data))
Then plot the result :
ggplot(data, aes(x=x)) +
stat_density(aes(y=..density..)) +
geom_text(aes(label=y, y=ypos)) +
facet_grid(z~., scales="free")
I want to facet three plots in rows of a single column using ggplot2, as illustrated below.
library(ggplot2)
df <- data.frame(x=rep(1,3), y=rep(1,3), z=factor(letters[1:3]))
p <- ggplot(df, aes(x, y)) + geom_point() + facet_grid(z ~ .)
p
There are two problems with this output. Most importantly, I want to control the scales of the x and y axes, in this case to make them the same i.e. a single unit should measure the same distance on both x and y axes.
The second issue is the colliding lables for y axis of the facetted plots. Bonus points for solving that, but full credit for the scale/aspect ratio problem.
I think you are looking for coord_fixed
library(ggplot2)
df <- data.frame(x=rep(1,3), y=rep(1,3), z=factor(letters[1:3]))
p <- ggplot(df, aes(x, y)) + geom_point() + facet_grid(z ~ .)
p + coord_fixed(ratio=1)
First, a quick example to set the stage:
set.seed(123)
dat <- data.frame(
x=rep( c(1, 2, 4, 7), times=25 ),
y=rnorm(100),
gp=rep(1:2, each=50)
)
p <- ggplot(dat, aes(x=factor(x), y=y))
p + geom_boxplot(aes(fill = factor(gp)))
I would like to produce a similar plot, except with control over the x position of each set of boxplots. My first guess was using a non-factor x aesthetic that controls the position along the x-axis of these box plots. However, once I try to do this it seems like geom_boxplot doesn't interpret the aesthetics as I would hope.
p + geom_boxplot( aes(x=x, y=y, fill=factor(gp)) )
In particular, geom_boxplot seems to collapse over all x values in some way when they're non-factors.
Is there a way to control the x position of boxplots with ggplot2? Either through specifying a distance between each level of a factor aesthetic, some more clever use of non-factor aesthetics, or otherwise?
You can use scale_x_discrete() to set positions (ticks) for the x axis.
p <- ggplot(dat, aes(x=factor(x), y=y))
p + geom_boxplot(aes(fill = factor(gp))) +
scale_x_discrete(limits=1:7)
You can also do this with the group aesthetic. However, I'm not sure why you cannot just pass x to the group. This doesn't work:
ggplot() +
geom_boxplot(data=dat, aes(x=x, y=y, fill=factor(gp), group=x))
But this does:
ggplot() +
geom_boxplot(data=dat, aes(x=x, y=y, fill=factor(gp), group=paste(x, gp)))