ggplot set ylim min OR max - r

I am trying to make a plot where I could just specify the min or the max value for the y axis. But I get Error in if (zero_range(range)) { : missing value where TRUE/FALSE needed
From the documentation:
You can leave one value as NA to compute from the range of the data.
Thus, I did:
#Getting some data in
plot <- ggplot(mydata,
aes_string(y="yvar", x="xvar", colour="group", group="group", fill="group")
)
#Adding some error bars
plot <- plot + geom_errorbar(aes(ymax=agg+var, ymin=agg-var), size=0.5, colour="black", data=mydata)
plot <- plot + geom_point(size=4)
plot <- plot + geom_line(size=1)
#Here is when I just want to set y max
plot <- plot + coord_cartesian(ylim= c(NA, 100))
If I remove the ylim or change the NA to a numeric value, it works well. What am I missing here?

You can use expand limits to extend the axis in only one direction. For example:
ggplot(mtcars, aes(wt, mpg)) +
geom_point() +
expand_limits(y=c(NA, 50))
For your example, it would be:
plot + expand_limits(y=c(NA, 100))
You can even provide a single value. If that value is greater than the maximum of the data, it will expand the maximum. If lower than the minimum of the data, it will expand the minimum. In your example:
plot + expand_limits(y=100)
And here are two reproducible examples:
p = ggplot(mtcars, aes(wt, mpg)) +
geom_point()
p + expand_limits(y=-20)
p + expand_limits(y=200)

Related

Automatically setting the limits of an axis when the other is manually defined in ggplot2

Consider the following example:
ggplot(mtcars, aes(mpg, wt)) +
geom_point() +
coord_cartesian(c(15, 20))
It sets the the limits of the x-axis, but the y limits remain as with the original plot, leaving a huge empty area.
Is it possible to automatically adjust y limits in this case? Similar to what
ggplot(mtcars[mtcars$mpg>15&mtcars$mpg<20,], aes(mpg, wt)) +
geom_point()
would produce.
Such automatism would make it unnecessary to manually calculate the y limits (which is not even trivial unless expand=0, as one has to take into account how y limits are expanded compared to what is provided).
Why don't you just set the y limits too?
ggplot(mtcars, aes(mpg, wt)) +
geom_point() +
coord_cartesian(xlim = c(15, 20), ylim = c(2.5,4.5))
Of course you can calculate the limits beforehand with some function, but I'm not sure if that makes any sense, because to calculate the limits in a region, you will have to tell that function which are the limits of the region, which represents the same amount manual effort as putting those limits into the ggplot function directly.
Such a function could look like this:
find_ylimits <- function(data,xlim,overhead = 1){
filter <- xlim[1] <= data[[1]] & data[[1]] <= xlim[2]
c(min(data[[2]][filter])*overhead,
max(data[[2]][filter])*overhead)
}
And then you could make the plot as follows:
ggplot(mtcars, aes(mpg, wt)) +
geom_point() +
coord_cartesian(xlim = c(15, 20), ylim = find_ylimits(mtcars[,c("mpg","wt")],c(15,20)))

scale_color_gradient does not adhere to breaks [duplicate]

I'm plotting a lot of graphics and I'd like for all of them to have the same colour scale so I can compare one to another. Here's my code:
myPalette <- colorRampPalette(rev(brewer.pal(11, "Spectral")))
print(ggplot(mydata, aes(x= X, y= Y, colour= Z)) + geom_point(alpha=.5,size = 6) + scale_colour_gradientn(colours = myPalette(100)) + ylim(.1,.4) + xlim(1.5,2) + ggtitle(title))
Is there a way to set this colour scale?
Do I understand this correctly? You have two plots, where the values of the color scale are being mapped to different colors on different plots because the plots don't have the same values in them.
library("ggplot2")
library("RColorBrewer")
ggplot(subset(mtcars, am==0), aes(x=wt, y=mpg, colour=carb)) +
geom_point(size=6)
ggplot(subset(mtcars, am==1), aes(x=wt, y=mpg, colour=carb)) +
geom_point(size=6)
In the top one, dark blue is 1 and light blue is 4, while in the bottom one, dark blue is (still) 1, but light blue is now 8.
You can fix the ends of the color bar by giving a limits argument to the scale; it should cover the whole range that the data can take in any of the plots. Also, you can assign this scale to a variable and add that to all the plots (to reduce redundant code so that the definition is only in one place and not in every plot).
myPalette <- colorRampPalette(rev(brewer.pal(11, "Spectral")))
sc <- scale_colour_gradientn(colours = myPalette(100), limits=c(1, 8))
ggplot(subset(mtcars, am==0), aes(x=wt, y=mpg, colour=carb)) +
geom_point(size=6) + sc
ggplot(subset(mtcars, am==1), aes(x=wt, y=mpg, colour=carb)) +
geom_point(size=6) + sc
There may be a better way to do this, but I don't know of it. In the meantime, you need to make sure that the values argument of scale_colour_gradientn is such that the values of all your plots map to the correct colors. So here, I make two plots with the same mapping between 0-100, but one of them has values from 50-150:
mydata <- data.frame(X=runif(20), Y=runif(20), Z=runif(20, 0, 100))
p1 <- ggplot(mydata, aes(x=X, y=Y, colour=Z)) +
geom_point(alpha=.5, size = 6) +
scale_colour_gradientn(colours = myPalette(100), values=seq(0, 100, length.out=100)/100) +
ggtitle("Z: 0 - 100")
This is the key bit:
mydata2 <- data.frame(X=runif(20), Y=runif(20), Z=runif(20, 50, 150))
nrm.range.2 <- (range(mydata$Z) - min(mydata2$Z)) / diff(range(mydata2$Z))
nrm.vals <- seq(nrm.range.2[[1]], nrm.range.2[[2]], length.out=100)
Now make the second plot.
p2 <- ggplot(mydata2, aes(x=X, y=Y, colour=Z)) +
geom_point(alpha=.5, size = 6) +
scale_colour_gradientn(colours = myPalette(100), values=nrm.vals) +
ggtitle("Z: 50 - 150")
I don't know of anyway of forcing which range of value display on the scale, but to the extent you have multiple plots with non-overlapping ranges of Z values, you can create a third dummy plot with all the range and use that. Here I purposefully went off range to show that the values that overlap have the same colors.
Ok so taking the data set from the previous example:
library(ggplot2)
library(RColorBrewer)
library(gridExtra)
library(gtablegridExtra)
#Using the mtcars data set
#Generate plot 1
p1=ggplot(subset(mtcars, am==0), aes(x=wt, y=mpg, colour=carb)) +
geom_point(size=2)+
labs(title="Graph 1")+
scale_color_gradientn(colours=rainbow(5))
#Generate plot 2
p2=ggplot(subset(mtcars, am==1), aes(x=wt, y=mpg, colour=carb)) +
geom_point(size=2)+
labs(title="Graph 2")+
scale_color_gradientn(colours=rainbow(5))
So if we plot both graphs together using grid.arrange you should get this:
grid.arrange(arrangeGrob(p1,
p2,
nrow = 1))
Graphs without equivalent color scale
So we want to get the same range for both graphs and plot only one of this colos sacles. What you need to do is first define the range of the of your color scale. in this example lets do it from:
summary(mtcars$carb)
>
Min. 1st Qu. Median Mean 3rd Qu. Max.
1.000 2.000 2.000 2.812 4.000 8.000
So we know that the color scale should be from 1 to 8. We define this range as col.range and we then use it to specify the range in each graph:
#Define color range
col.range=c(1,8)
#Generate plot 1
p1=ggplot(subset(mtcars, am==0), aes(x=wt, y=mpg, colour=carb)) +
geom_point(size=2)+
labs(title="Graph 1")+
scale_color_gradientn(colours=rainbow(5),limits=col.range) #look here
#Generate plot 2
p2=ggplot(subset(mtcars, am==1), aes(x=wt, y=mpg, colour=carb)) +
geom_point(size=2)+
labs(title="Graph 2")+
scale_color_gradientn(colours=rainbow(5),limits=col.range) #look here
#Plot both graphs together
grid.arrange(arrangeGrob(p1,
p2,
nrow = 1))
This will get you the following graph. Now the color is comparable between both graphs.
Graphs with same color scale
However the repeated colos scale is redundant, so we want to use only one.
So to get that nice final graph we can use the same p1 and p2 graphs that we defined previously, we just especified on the grid.arrange function as:
#Create al element that will represent your color scale:
color.legend=gtable_filter(ggplotGrob(p1),"guide-box")
#We hide de color scale on each individual graph
#Then we insert the color scale and we adjust the ratio of it with the graphs
#For this we define the theme() as follows:
grid.arrange(arrangeGrob(p1+theme(legend.position="none"),
p2+theme(legend.position="none"),
nrow = 1), #Here we have just remove the color scale
color.scale, #We inserted the color scale.
nrow=1, #We put the color scale to the right of the graph
widths=c(20,1) #With this we make the color scale much narrower
So with this you are done, getting the following graph:
Graphs with just one color scale
Hope is is usefull!!!!!!
Please rate!!!!! <3

how to make the value on Y axis start from zero in R, ggplot2

currently, I'm using ggplot2 to make density plot.
ggplot(data=resultFile,aes(x=V19, colour=V1) ) +
geom_line(stat="density") +
xlab("score") +
ylab("density") +
ggtitle(paste(data_name,protocol,level,sep=" ")) +
theme(legend.title=element_blank(), legend.position=c(0.92,0.9)) +
scale_color_manual(values=c("blue","red"),
labels=c("A", "B"))
using this code, I can get the plot below.
However, I can get different plot if I used plot(density()...) function in R.
Y value starts from 0.
How can I make the ggplot's plot as like plot(density()...) in R?
ggplot(data=resultFile,aes(x=V19, colour=V1) ) +
ylim(0,range) #you can use this .
geom_line(stat="density") +
xlab("score") +
ylab("density") +
ggtitle(paste(data_name,protocol,level,sep=" ")) +
theme(legend.title=element_blank(), legend.position=c(0.92,0.9)) +
scale_color_manual(values=c("blue","red"),
labels=c("A", "B"))
ggplot obviously cut off the x-axis at the min and max of the empirical distribution. You can extend the x-axis by adding xlim to the plot but please make sure that the plot does not exceed the theoretical limit of the distribution (in the example below, the theoretical limit is [0, 1], so there is not much reason to show outside the range).
set.seed(1)
temp <- data.frame(x =runif(100)^3)
library(ggplot2)
ggplot(temp, aes(x = x)) + geom_line(stat = "density" + xlim(-.2, 1.2)
plot(density(temp$x))

In ggplot2, how can I limit the range of geom_hline?

Taking a simple plot from ggplot2 manual
p <- ggplot(mtcars, aes(x = wt, y=mpg)) + geom_point()
p + geom_hline(yintercept=20)
I get a horizontal line at value 20, as advertised.
Is there a way to limit the range of this line on x axis, to let's say2 - 4 range?
You can use geom_segment() instead of geom_hline() and provide x= and xend= values you need.
p+geom_segment(aes(x=2,xend=4,y=20,yend=20))

How to use scale from previous plot in current plot with ggplot2?

I am using ggplot2 to produce a plot that has 3 facets. Because I am comparing two different data sets, I would like to then be able to plot a second data set using the same y scale for the facets as in the first plot. However, I cannot find a simple way to save the settings of the first plot to then re-use them with the second plot. Since each facet has its own y scale, it will be a pain to specify them by hand for the second plot. Does anyone know of a quick way of re-using scales? To make this concrete, here is how I am generating first my plot:
p <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p + facet_wrap(~ cyl, scales = "free_y")
EDIT
When applying one of the suggestions below, I found out that my problem was more specific than described in the original post, and it had to do specifically with scaling of the error bars. Concretely, the error bars look weird when I rescale the second plot as suggested. Does anyone have any suggestions on how to keep the same scale for both plots and dtill display the error bars correctly? I am attaching example below for concreteness:
#Create sample data
d1 <- data.frame(fixtype=c('ff','ff','fp','fp'), detype=c('det','pro','det','pro'),
diffscore=c(-1,-15,3,-17),se=c(2,3,1,2))
d2 <- data.frame(fixtype=c('ff','ff','fp','fp'), detype=c('det','pro','det','pro'),
diffscore=c(-1,-3,-2,-1),se=c(4,3,5,3))
#Plot for data frame 1, this is the scale I want to keep
lim_d1 <- aes(ymax = diffscore + se, ymin=diffscore - se)
ggplot(d1, aes(colour=detype, y=diffscore, x=detype)) +
geom_point(aes(size=1), shape=15) +
geom_errorbar(lim_d1, width=0.2,size=1) +
facet_wrap(~fixtype, nrow=2, ncol=2, scales = "free_y")
#Plot for data frame 2 original scale
lim_d2 <- aes(ymax = diffscore + se, ymin=diffscore - se)
ggplot(d2, aes(colour=detype, y=diffscore, x=detype)) +
geom_point(aes(size=1), shape=15) +
geom_errorbar(lim_d2, width=0.2,size=1) +
facet_wrap(~fixtype, nrow=2, ncol=2, scales = "free_y")
#Plot for data frame 2 adjusted scale. This is where things go wrong!
#As suggested below, first I plot the first plot, then I draw a blank screen and try
#to plot the second data frame on top.
lim_d2 <- aes(ymax = diffscore + se, ymin=diffscore - se)
ggplot(d1, aes(colour=detype, y=diffscore, x=detype)) +
geom_blank() +
geom_point(data=d2, aes(size=1), shape=15) +
geom_errorbar(lim_d2, width=0.2,size=1) +
facet_wrap(~fixtype, nrow=2, ncol=2, scales = "free_y")
#If the error bars are fixed, by adding data=d2 to geom_errorbar(), then
#the error bars are displayed correctly but the scale gets distorted again
lim_d2 <- aes(ymax = diffscore + se, ymin=diffscore - se)
ggplot(d1, aes(colour=detype, y=diffscore, x=detype)) +
geom_blank() +
geom_point(data=d2, aes(size=1), shape=15) +
geom_errorbar(data=d2,lim_d2, width=0.2,size=1) +
facet_wrap(~fixtype, nrow=2, ncol=2, scales = "free_y")
You may first call ggplot on your original data where you add a geom_blank as a first layer. This sets up a plot area, with axes and legends based on the data provided in ggplot.
Then add geoms which use data other than the original data. In the example, I use a simple subset of the original data.
From ?geom_blank: "The blank geom draws nothing, but can be a useful way of ensuring common scales between different plots.".
ggplot(data = mtcars, aes(mpg, wt)) +
geom_blank() +
geom_point(data = subset(mtcars, wt < 3)) +
facet_wrap(~ cyl, scales = "free_y")
Here is an ugly hack that assumes you have an identical facetting layout in both plots.
It replaces the panel element of the ggplot build.
p <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p1 <- p + facet_wrap(~ cyl, scales = "free_y") + labs(title = 'original')
# create "other" data.frame
n <- nrow(mtcars)
set.seed(201405)
mtcars2 <- mtcars[sample(seq_len(n ),n-15),]
# create this second plot
p2 <- p1 %+% mtcars2 + labs(title = 'new data')
# and a copy so we can attempt to fix
p3 <- p2 + labs(title = 'new data original scale')
# use ggplot_build to construct the plots for rendering
p1b <- ggplot_build(p1)
p3b <- ggplot_build(p3)
# replace the 'panel' information in plot 2 with that
# from plot 1
p3b[['panel']] <- p1b[['panel']]
# render the revised plot
# for comparison
library(gridExtra)
grid.arrange(p1 , p2, ggplot_gtable(p3b))

Resources