I make a heatmap within ggplot that looks something like that:
set.seed(1)
n <- 100
df <- data.frame(x= rnorm(n), y= rnorm(n), z= rnorm(n))
df$z[1:20] <- NA
ggplot() +
geom_point(data= subset(df, !is.na(z)), mapping= aes(x, y, col= z)) +
geom_point(data= subset(df, is.na(z)), mapping= aes(x, y), col= "black", shape= 4)
Here the points of the scatterplot change colours depending on values in z. Further, I added black crosses (shape 4) to visualize missings in z. I want to add the same x as in the plot to the legend saying missing above it. How can we do this?
I'd actually put the overall command in the same geom_point function using the shape parameter and then manually set the parameters with scale_shape_manual:
ggplot(df) +
geom_point(aes(x, y, colour = z, shape = is.na(z))) +
scale_shape_manual(name = "Missing values", values=c(16, 4))
Related
I have a set of data predicted by a model. I'm plotting it with geom_tile().
df1 <- data.frame(x=rep(seq(0,10,by=.1),each=101),
y=rep(seq(10,20,by=.1),times=101))
df1$z <- ((.1*df1$x^2+df1$y)-10)/20
library("ggplot2")
ggplot(mapping=aes(x=x,y=y,size=5,color=z),data=df1)+
geom_point(size = 16, shape = 15)
ggplot(df1, aes(x, y, fill="blue",alpha = z)) + geom_tile()
How can I add some contour lines to it at specific values (e.g. z=0.9, 0.95, 0.99)? Alternatively, geom_tile can be changed to any suitable continuous / contour / raster plot function.
ggplot(df1, aes(x, y, z = z, fill = z))+
geom_tile()+
geom_contour()
I'm using ggplot to create a heat-map style plot, and would like to add a second legend with the data scaled a different way. I'm wondering if there is a simple way to do this.
I do not believe that this is a duplicate of other "multiple legends" questions e.g. Multiple legends for a ggplot in R as crucially I want to add extra legends for the same aesthetic - i.e. one aesthetic mapping, two legends.
Example code
# Create a dataframe with some dummy data
x <- c()
y <- c()
for(i in 1:100){
for(j in 1:100){
x <- c(x, i)
y <- c(y, j)
}
}
example_data <- data.frame(x, y)
example_data$z <- example_data$x*example_data$y
example_data$z_rescale <- example_data$z*0.5
Now we've got some data that I'd like to plot as a heatmap with "z" as a colour gradient.
ggplot(example_data, aes(x = x, y = y, fill = z)) +
geom_tile() +
scale_fill_gradient(low = "blue", high = "red") +
scale_x_continuous(expand = c(0, 0)) +
scale_y_continuous(expand = c(0, 0))
Doing the same with the rescaled z gives an identical plot, but with the rescaled legend:
ggplot(example_data, aes(x = x, y = y, fill = z_rescale)) +
geom_tile() +
scale_fill_gradient(low = "blue", high = "red") +
scale_x_continuous(expand = c(0, 0)) +
scale_y_continuous(expand = c(0, 0))
What I'd like to do however is have a single plot showing the two different legends, which would look something like this mock-up:
Now, I imagine this would be possible by creating two plots, finding the grob that represents the legend in one of the plots and cunningly adding it to the second plot... however, is there a much simpler way that I'm overlooking?
Many thanks!
Please add the code
aes(color = z_rescale) +
scale_color_gradient(low = "blue", high = "red") +
after geom_tile() line and you will get the desired
I want to make a line chart in plotly so that it does not have the same color on its whole length. The color is given continuous scale. It is easy in ggplot2 but when I translate it to plotly using ggplotly function the variable determining color behaves like categorical variable.
require(dplyr)
require(ggplot2)
require(plotly)
df <- data_frame(
x = 1:15,
group = rep(c(1,2,1), each = 5),
y = 1:15 + group
)
gg <- ggplot(df) +
aes(x, y, col = group) +
geom_line()
gg # ggplot2
ggplotly(gg) # plotly
ggplot2 (desired):
plotly:
I found one work-around that, on the other hand, behaves oddly in ggplot2.
df2 <- df %>%
tidyr::crossing(col = unique(.$group)) %>%
mutate(y = ifelse(group == col, y, NA)) %>%
arrange(col)
gg2 <- ggplot(df2) +
aes(x, y, col = col) +
geom_line()
gg2
ggplotly(gg2)
I also did not find a way how to do this in plotly directly. Maybe there is no solution at all. Any ideas?
It looks like ggplotly is treating group as a factor, even though it's numeric. You could use geom_segment as a workaround to ensure that segments are drawn between each pair of points:
gg2 = ggplot(df, aes(x,y,colour=group)) +
geom_segment(aes(x=x, xend=lead(x), y=y, yend=lead(y)))
gg2
ggplotly(gg2)
Regarding #rawr's (now deleted) comment, I think it would make sense to have group be continuous if you want to map line color to a continuous variable. Below is an extension of the OP's example to a group column that's continuous, rather than having just two discrete categories.
set.seed(49)
df3 <- data_frame(
x = 1:50,
group = cumsum(rnorm(50)),
y = 1:50 + group
)
Plot gg3 below uses geom_line, but I've also included geom_point. You can see that ggplotly is plotting the points. However, there are no lines, because no two points have the same value of group. If we hadn't included geom_point, the graph would be blank.
gg3 <- ggplot(df3, aes(x, y, colour = group)) +
geom_point() + geom_line() +
scale_colour_gradient2(low="red",mid="yellow",high="blue")
gg3
ggplotly(gg3)
Switching to geom_segment gives us the lines we want with ggplotly. Note, however, that line color will be based on the value of group at the first point in the segment (whether using geom_line or geom_segment), so there might be cases where you want to interpolate the value of group between each (x,y) pair in order to get smoother color gradations:
gg4 <- ggplot(df3, aes(x, y, colour = group)) +
geom_segment(aes(x=x, xend=lead(x), y=y, yend=lead(y))) +
scale_colour_gradient2(low="red",mid="yellow",high="blue")
ggplotly(gg4)
I am trying to make a plot using several contour levels with geom_contour. Each of these levels defines a zone onto which I plot points with geom_point. My problem is that I don't manage to have on the same plot a color scale for the points and one for the levels, either the same or another.
MWE:
X <- data.frame(x1 = rnorm(1e4), x2 = rnorm(1e4))
X$z <- sqrt(rowSums(X^2))
X$level <- factor(floor(X$z))
xplot <- yplot <- c(-80:80)/10
df_plot = data.frame(expand.grid(x1=xplot, x2=yplot))
df_plot$z = sqrt(rowSums(df_plot^2))
# plot several contour
ggplot(data = df_plot, aes(x1,x2)) + geom_contour(aes(z=z, color=..level..), breaks = c(1:5))
# plot points with colors corresponding to zone
ggplot(data = X, aes(x1,x2)) + geom_point(aes(color=level))
# plot both
ggplot(data = X, aes(x1,x2)) + geom_point(aes(color=level)) +
geom_contour(data = df_plot, aes(z=z), breaks = 1:5)
On this third plot I'd like to have the levels with the same colors as the points, or at least an other color scale. I've tried to put color= in and out aes but it does not change anything.
thanks
The issue here is that you are mixing a discrete and a continuous colour scale (for the points and the contours, respectively) and ggplot2 uses different defaults for the two. By making the colour scale for the contours discrete as well, you can get the same colours:
ggplot(data = X, aes(x = x1, y = x2)) + geom_point(aes(colour = level)) +
geom_contour(data = df_plot, aes(z = z, colour = factor(..level.. - 1)),
breaks = 0:5, size = 1)
Note that I have reduced the number of points and increased the thickness of the lines to make the lines better visible
This is a slightly long winded way of getting what you want, but you get there in the end.
ggplot(data = X, aes(x1,x2)) +
geom_point(aes(color=level)) + # Now add each contour separately.
geom_contour(data = df_plot, aes(z=z), breaks = 1, colour=rainbow(8)[1]) +
geom_contour(data = df_plot, aes(z=z), breaks = 2, colour=rainbow(8)[2]) +
scale_colour_manual(values=rainbow(8))
I have a plot with three different lines. I want one of those lines to have points on as well. I also want the two lines without points to be thicker than the one without points. I have managed to get the plot I want, but I the legend isn't keeping up.
library(ggplot2)
y <- c(1:10, 2:11, 3:12)
x <- c(1:10, 1:10, 1:10)
testnames <- c(rep('mod1', 10), rep('mod2', 10), rep('meas', 10))
df <- data.frame(testnames, y, x)
ggplot(data=df, aes(x=x, y=y, colour=testnames)) +
geom_line(aes(size=testnames)) +
scale_size_manual("", values=c(0.5,1,1)) +
geom_point(aes(alpha=testnames), size=5, shape=4) +
scale_alpha_manual("", values=c(1, 0, 0))
I can remove the second (black) legend:
ggplot(data = df, aes(x=x, y=y, colour=testnames)) +
geom_line(aes(size=testnames)) +
scale_size_manual("", values=c(0.5,1,1), guide='none') +
geom_point(aes(alpha=testnames), size=5, shape=4) +
scale_alpha_manual("", values=c(1, 0.05, 0.05), guide='none')
But what I really want is a merge of the two legends - a legend with colours, cross only on the first variable (meas) and the lines of mod1 and mod2 thicker than the first line. I have tried guide and override, but with little luck.
You don't need transparency to hide the shapes for mod1 and mod2. You can omit these points from the plot and legend by setting their shape to NA in scale_shape_manual:
ggplot(data = df, aes(x = x, y = y, colour = testnames, size = testnames)) +
geom_line() +
geom_point(aes(shape = testnames), size = 5) +
scale_size_manual(values=c(0.5, 2, 2)) +
scale_shape_manual(values=c(8, NA, NA))
This gives the following plot:
NOTE: I used some more distinct values in the size-scale and another shape in order to better illustrate the effect.