I am having issue while drawing a graph with ribbons. I came across a sample script in a thread here. That has the same problem.
Below is the script from the thread (slightly modified)
x=1:10
y1=1:10
y2=2:11
y3=10:1
y4=9:0
dt=data.frame(x,y1,y2,y3,y4)
library(ggplot2)
g<-ggplot(dt)+
geom_ribbon(aes(x=x,ymin=y1,ymax=y2,fill='red'),
alpha=0.4)
g<-g + geom_ribbon(aes(x=x,ymin=y3,ymax=y4,fill='blue'),
alpha=0.5)
g<-g + scale_fill_manual(name='legendname',
values=c('red','blue'),
labels=c('one','two'))
The script draws two ribbons called "one" and "two". Ribbon "one" (going up) is supposed to be red and "two" (going down) is supposed to be blue. But the colours are reversed.
If the script is executed step by step you will see that the ribbon one gets drawn as red first and when ribbon two gets drawn it changes colour.
I am totally new to R. So explain to me what is happening here?
According to the ggplot2 documentation (p.10), when you set the argument fill in the aesthetic, you're basically creating a color scale (could be either continuous or discrete, depending on the argument). I'm not sure about the internal implementation of the aes function, but I'm suspecting that since you're passing it a color string, instead of a vector of possible values, the fill argument is simply ignored.
In fact, if you view g before you apply the scale_fill_manual function, you'll see that ggplot2 assigns its default colors to the ribbons, instead of the colors that you selected:
And the reason why the colors are reversed at the end is because when you apply the scale_fill_manual, the color red goes to the layer on top, and the color blue goes to the layer below it.
To get the colors right, what you can do is assign the fill argument to geom_ribbon instead of aes, as follows:
g <- ggplot(dt)
g <- g + geom_ribbon(aes(x=x, ymin=y1, ymax=y2), fill = 'red', alpha=0.4)
g <- g + geom_ribbon(aes(x=x, ymin=y3, ymax=y4), fill = 'blue', alpha=0.5)
Also, you don't need the color scale at the end for this particular example.
Related
I am doing kmeans clustering on a png image and have been plotting it using grid::grid.raster(image). But I would like to put a legend which shows the intensity in a bar(from blue to red) marked with values, essentially indicating the intensity on the image. (image is an array where the third dimension equals 3 giving the red, green and blue channels.)
I thought of using grid.legend() but couldn't figure it out. I am hoping the community can help me out. Following is the image I have been using and after I perform kmeans clustering want a legend beside it that displays intensity on a continuous scale on a color bar.
Also I tried with ggplot2 and could plot the image but still couldn't plot the legend. I am providing the ggplot code for plotting the image. I can extract the RGB channels separately using ggplot2 also, so showing that also helps.
colassign <- rgb(Kmeans2#centers[clusters(Kmeans2),])
library(ggplot2)
ggplot(data = imgVEC, aes(x = x, y = y)) +
geom_point(colour = colassign) +
labs(title = paste("k-Means Clustering of", kClusters, "Colours")) +
xlab("x") +
ylab("y")
Did not find a way to use grid.raster() properly but found a way to do it by ggplot2 when plotting the RGB channels separately. Note: this only works for plotting the pannels separately, but this is what I needed. Following shows the code for green channel.
#RGB channels are respectively stored in columns 1,2,3.
#x-axis and y-axis values are stored in columns 4,5.
#original image is a nx5 matrix
ggplot(original_img[,c(3,4,5)], aes(x, y)) +
geom_point(aes(colour = segmented_img[,3])) +
scale_color_gradient2()+
# scale_color_distiller(palette="RdYlBu") can be used instead of scale_color_gradient2() to get color selections of choice using palette as argument.
Working with RStudio 0.98.1103, I am creating two versions of exactly the same graph: One with colors and one without. Since both graphs are exactly the same (apart from the coloring) I want to avoid typing nearly the same commands again. Hence, I create the colored plot, save it, manipulate it to make it black-grey-white and save the reduced version:
library(ggplot2)
bp <- ggplot(data=PlantGrowth, aes(x=group, y=weight)) +
geom_line(aes(color=group)) + theme(legend.position="none")
bp_bw <- bp + theme_bw() +
geom_line() + theme(legend.position="none")
ggsave("bp_bw.png", bp_bw)
Although bp looks quite normal, bp_bw doesn't. There is still a blury color shining behind the black bars (red - green - blue):
Closeup:
How can I get rid of this colors, i.e. remove all color completely from bp? Only restriction: I have to create the colored graphs first (although of course a different order would work).
I think a better solution is to create a base and only add the coloring part when needed:
bp <- ggplot(data=PlantGrowth, aes(x=group, y=weight)) +
theme_bw() + theme(legend.position="none")
bp_col <- bp + geom_line(aes(color=group))
bp_bw <- bp + geom_line()
This (more-or-less) makes sense. Your bp_bw code doesn't get rid of the old colored lines, it just adds black lines on top. Anti-aliasing as the image is displayed/saved lets some of the color through on the edges.
My recommendation is to modify the color scale rather than overplot black on top:
bp_bw2 = bp + scale_color_manual(values = rep("black", 20)) + theme_bw()
This will change the colors to all black rather than plotting black on top of colors. The rep("black", 20) is kind of a hack. Apparently values aren't recycled by scale_color_manual, but extra values aren't used so you need to give it a vector at least as long as the number of colors.
This also has the advantage of not needing to repeat the geom call, and if you had previously defined a color scale this will overwrite it. If you want to be more general you could also add a scale_fill_manual(), and you probably want to specify guide = FALSE so that you don't get a very unhelpful legend.
You also might want to check out scale_colour_grey, just because it's B&W doesn't mean all the colors have to be the same.
I am using ggplot2 to create several plots about the same data. In particular I am interested in plotting observations according to a factor variable with 6 levels ("cluster").
But the plots produced by ggplot2 use different palettes every time!
For example, if I make a bar plot with this formula I get this result (this palette is what I expect to obtain):
qplot(cluster, data = data, fill = cluster) + ggtitle("Clusters")
And if I make a scatter plot and I try to color the observations according to their belonging to a cluster I get this result (notice that the color palette is different):
ggplot(data, aes(liens_ratio,RT_ratio)) +
geom_point(col=data$cluster, size=data$nombre_de_tweet/100+2) +
geom_smooth() +
ggtitle("Links - RTs")
Any idea on how to solve this issue?
I can't be certain this will work in your specific case without a reproducible example, but I'm reasonably confident that all you need to do is set your color inside an aes() call within the geom you want to color. That is,
ggplot(data, aes(x = liens_ratio, y = RT_ratio)) +
geom_point(aes(color = cluster, size = nombre_de_tweet/100+2)) +
geom_smooth() +
ggtitle("Links - RTs")
If all plots you make use the same data and this basic format, the color palette should be the same regardless of the geom used. Additional elements, such as the line from geom_smooth() will not be changed unless they are also explicitly colored.
The palette will just be the default one, of course; to change it look into scale_color_manual.
I have ordered categorical data that I would like to use color brewer on. But I have a hard time seeing the very light lower values. Is there a way to either trim off those lower values or set the lower limit in the scale?
ggplot(data.frame(x=1:6, y=10:15, w=letters[1:6]), aes(x, y, color=w)) +
geom_point()+ scale_color_brewer(type="seq", palette=1) + theme_bw()
Is there a better way to do this? So far I either see qualitative scales that aren't ordered or continuous scales that don't like being applied to discrete data. I'm aware of manual scales if that's the only route.
You cannot just set a lower limit. But you can use a palette with more colors than needed and map the brightest colors to unused levels. Below is an example with 9 levels:
ggplot(data.frame(x=1:6, y=10:15, w=letters[1:6]), aes(x, y, color=w)) +
geom_point() + theme_bw() +
scale_color_brewer(type="seq", palette=1,
limits=c(LETTERS[1:3], letters[1:6]),
breaks=letters[1:6])
While #shadow's answer was a start for me, the kind of brewer palette I needed to use (sequential) only has 9 values -- I had 8 categorical variables to plot! Removing only the 9th and lightest palette color still wasn't enough to make the color scheme completely visible.
So I used the colorRampPalette() function, which allows you to expand existing color palettes into continuous functions:
library(RColorBrewer)
ggplot(data.frame(x=1:6, y=10:15, w=letters[1:6]), aes(x, y, color=w)) +
geom_point() + theme_bw() +
scale_color_manual(values = colorRampPalette(brewer.pal(9, "YlGnBu"))(12)[6:12])
So in this case, I'm mapping the (maximum) 9 native colors from the "YlGnBu" palette onto 12 colors, and then only using the darkest 6 of those colors ([6:12]) in the plot.
I'm not aware of any additional arguments you could pass to scale_colour_brewer() to set the lower limit of the scale (see http://docs.ggplot2.org/current/scale_brewer.html)
You have more flexibility with one of ggplot's colour options, which take the format of: scale_xxx_yyy, for example scale_fill_discrete() which take more arguments. See for example http://docs.ggplot2.org/current/scale_hue.html but also note the other options ('see also').
scale_fill_continuous might be a good starting place for ordinal data as you've requested.
You could, for example, pass colours from http://colorbrewer2.org/ to it, and choose a more suitable starting colour. The only problem is you would need to convert the rgb/hex values to HSL values using a tool such as: http://serennu.com/colour/hsltorgb.php
I've created a map by overlaying polygons using spplot and with the alpha value of the fill set to 10/255 so that areas with more polygons overlapping have a more saturated color. The polygons are set to two different colors (blue and red) based on a binary variable in the attribute table. Thus, while the color saturation depends on the number of polygons overlapping, the color depends on the ratio of the blue and red classes of polygons.
There is, of course, no easy built-in legend for this so I need to create one from scratch. There is a nice solution to this in base graphics found here. I also came up with a not-so-good hack to do this in ggplot based on this post from kohske. A similar question was posted here and I did my best to give some solutions, but couldn't really come up with a solid answer. Now I need to do the same for myself, but I specifically would like to use R and also use grid graphics.
This is the ggplot hack I came up with
Variable_A <- 100 # max of variable
Variable_B <- 100
x <- melt(outer(1:Variable_A, 1:Variable_B)) # set up the data frame to plot from
p <- ggplot(x) + theme_classic() + scale_alpha(range=c(0,0.5), guide="none") +
geom_tile(aes(x=Var1, y=Var2, fill="Variable_A", col.regions="red", alpha=Var1)) +
geom_tile(aes(x=Var1, y=Var2, fill="Variable_B", col.regions="blue", alpha=Var2)) +
scale_x_continuous(limits = c(0, Variable_A), expand = c(0, 0)) +
scale_y_continuous(limits = c(0, Variable_B), expand = c(0, 0)) +
xlab("Variable_A") + ylab("Variable_B") +
guides(fill=FALSE)
p
Which gives this:
This doesn't work for my purposes for two reasons. 1) Because the alpha value varies, the second color plotted (blue in this case) overwhelms the first one as the alpha values get higher. The correct legend should have blue and red mixed evenly along the 1:1 diagonal. In addition, the colors don't really properly correspond to the map colors. 2) I don't know how to overlay a ggplot object on the lattice map created with spplot. I tried to create a grob using ggplotGrob(p), but still couldn't figure out how to add the grob to the spplot map.
The ideal solution would be to create a similar figure using lattice graphics. I think that using tiles is probably the right solution, but what would be best is to have the alpha values stay constant and vary the number of tiles plotted going from left to right (for red) and bottom to top (for blue). Thus, the colors and saturation should properly match the map (I think...).
Any help is much appreciated!
How about mapping the angle to color, and alpha to the sum of the two variables -- does this do what you want?
d <- expand.grid(x=1:100, y=1:100)
ggplot(d, aes(x, y, fill=atan(y/x), alpha=x+y)) +
geom_tile() +
scale_fill_gradient(high="red", low="blue")+
theme(legend.position="none", panel.background=element_blank())