I'm having an issue when exporting stat_density2d plots.
ggplot(faithful, aes(eruptions, y = waiting, alpha = ..density..)) +
stat_density2d(geom = 'tile', contour = F)
When exporting as a png it looks like so:
But when I export as a PDF a grid appears:
I'm assuming that this is because the boundaries of the tiles overlap and so have equivalent of a doubled alpha value.
How can I edit just the edges of the tiles to stop this from happening?
Secondary question:
As Tjebo mentioned geom = 'raster' would fix this problem. However, this raises a new issue that only one group gets plot.
df <- faithful
df$new <- as.factor(ifelse(df$eruptions>3.5, 1, 0))
ggplot(df, aes(eruptions, waiting, fill = new, alpha = ..density..)) +
stat_density2d(geom = 'tile', contour = F) +
scale_fill_manual(values = c('1' = 'blue', '0' = 'red'))
ggplot(df, aes(eruptions, waiting, fill = new, alpha = ..density..)) +
stat_density2d(geom = 'raster', contour = F) +
scale_fill_manual(values = c('1' = 'blue', '0' = 'red'))
help on this second issue would also be much appreciated!
Now I decided to transform my comment into an answer instead. Hopefully it solves your problem.
There is an old, related google thread on this topic - It seems related to how the plots are vectorized in each pdf viewer.
A hack is suggested in this thread, but one solution might simply be to use geom = 'raster' instead.
library(ggplot2)
ggplot(faithful, aes(eruptions, y = waiting, alpha = ..density..)) +
stat_density2d(geom = 'raster', contour = F)
Created on 2019-08-02 by the reprex package (v0.3.0)
If you have a look at the geom_raster documentation - geom_raster is recommended if you want to export to pdf!
The most common use for rectangles is to draw a surface. You always want to use geom_raster here because it's so much faster, and produces smaller output when saving to PDF
edit - second part of the question
Your tile plot can't be correct - you are creating cut-offs (your x value), so the fill should not overlap. This points to the core of the problem - the alpha=..density.. probably calculates the density based on the entire sample, and not by group. I think the only way to go is to pre-calculate the density (e.g., using density(). In your example, for demonstration purpose, we have this luckily precalculated, as faithfuld (this is likely not showing the results which you really want, as it is the density on the entire sample!!).
I'd furthermore recommend not to use numbers as your factor values - this is pretty confusing for you and R. Use characters instead. Also, ideally don't use df for a sample data frame, as this is a base R function;)
Hope this helps
mydf <- faithfuld ## that is crucial!!! faithfuld contains a precalculated density column which is needed for the plot!!
mydf$new <- as.factor(ifelse(mydf$eruptions>3.5, 'large', 'small'))
ggplot(mydf, aes(eruptions, waiting)) +
geom_raster(aes(fill = new, alpha = density), interpolate = FALSE)
Created on 2019-08-02 by the reprex package (v0.3.0)
Related
I have a two small sets of points, viz. (1,a1),...,(9,a9) and (1,b1),...,(9,b9). I'm trying to interpolate these two set of points separately by using splines with the help of ggplot2. So, what I want is 2 different splines curves interpolating the two sets of points on the same plot (Refer to the end of this post).
Since I have a very little plotting experience using ggplot2, I copied a code snippet from this answer by Richard Telford. At first, I stored my Y-values for set of points in two numeric variables A and B, and wrote the following code :
library(ggplot2)
library(plyr)
A <- c(a1,...,a9)
B <- c(b1,...,b9)
d <- data.frame(x=1:9,y=A)
d2 <- data.frame(x=1:9,y=B)
dd <- rbind(cbind(d, case = "d"), cbind(d2, case = "d2"))
ddsmooth <- plyr::ddply(dd, .(case), function(k) as.data.frame(spline(k)))
ggplot(dd,aes(x, y, group = case)) + geom_point() + geom_line(aes(x, y, group = case), data = ddsmooth)
This produces the following output :
Now, I'm seeking for an almost identical plot with the following customizations :
The two spline curves should have different colours
The line width should be user's choice (Like we do in plot function)
A legend (Specifying the colour and the corresponding attribute)
Markings on the X-axis should be 1,2,3,...,9
Hoping for a detailed solution to my problem, though any kind of help is appreciated. Thanks in advance for your time and help.
You have already shaped your data correctly for the plot. It's just a case of associating the case variable with colour and size scales.
Note the following:
I have inferred the values of A and B from your plot
Since the lines are opaque, we plot them first so that the points are still visible
I have included size and colour parameters to the aes call in geom_line
I have selected the colours by passing them as a character vector to scale_colour_manual
I have also selected the sizes of the lines by calling scale_size_manual
I have set the x axis breaks by adding a call to scale_x_continuous
The legend has been added automatically according to the scales used.
ggplot(dd, aes(x, y)) +
geom_line(aes(colour = case, size = case, linetype = case), data = ddsmooth) +
geom_point(colour = "black") +
scale_colour_manual(values = c("red4", "forestgreen"), name = "Legend") +
scale_size_manual(values = c(0.8, 1.5), name = "Legend") +
scale_linetype_manual(values = 1:2, name = "Legend") +
scale_x_continuous(breaks = 1:9)
Created on 2020-07-15 by the reprex package (v0.3.0)
I am trying to generate a heatmap where I can show more than one level of information on each cell. For each cell I would like to show a different color depending on its value in one variable and then overlay this with a transparency (alpha) that shades the cell according to its value for another variable.
Similar questions have been addressed here (Place 1 heatmap on another with transparency in R) a
and here (Making a heatmap in R varying both color and transparency). In both cases the suggestion is to use ggplot and overlay two geom_tiles, one with the colors one with the transparency.
I have managed to overlay two geom_tiles (see code below). However, in my case, the problem is that the shading defined by the transparency (or "alpha") geom_tile also shades some cells that should remain as white or blank according to the colors (or "fill") geom_tile. I would like these cells to remain white even after overlaying the transparency.
#Create sample dataframe
df <- data.frame("x_pos" = c("A","A","A","B","B","B","C","C","C"),
"y_pos" = c("X","Y","Z","X","Y","Z","X","Y","Z"),
"col_var"= c(1,2,NA,4,5,6,NA,8,9),
"alpha_var" = c(7,12,0,3,2,15,0,6,15))
#Convert factor columns to numeric
df$col_var<- as.numeric(df$col_var)
df$alpha_var<- as.numeric(df$alpha_var)
#Cut display variable into breaks
df$col_var_cut <- cut(df$col_var,
breaks = c(0,3,6,10),
labels = c("cat1","cat2", "cat3"))
#Plot
library(ggplot2)
ggplot(df, aes (x = x_pos, y = y_pos, fill = col_var_cut, label = col_var)) +
geom_tile () +
geom_text() +
scale_fill_manual(values=(brewer.pal(3, "RdYlBu")),na.value="white") +
geom_tile(aes(alpha = alpha_var), fill ="gray29")+
scale_alpha_continuous("alpha_var", range=c(0,0.7), trans = 'reverse')+
theme_bw() +
theme(axis.text.x = element_text(angle = 90, hjust = 1))
I would like cells "AZ" and "CX" in the heatmap resulting from the code above to be colored white instead of grey such that the alpha transparency doesn't apply to them. In my data, these cells have NA in the color variable (col_var) and can have a value of NA or 0 (as in the example code) in the transparency/alpha variable (alpha_var).
If this is not possible, then I would like to know whether there are other options to display both variables in a heatmap and keep the NA cells in the col_var white? I am happy to use other packages or alternative heatmap layouts such as those where the size of each cell or the thickness of its border vary according to the values the alpha_var. However, I am not sure how I could achieve this either.
Thanks in advance and my apologies for the cumbersome bits in the example code (I am still learning R and this is my first time asking questions here).
You were not far. See below for a possible solution. The first plot shows an implementation of adding transparency within the geom_tile call itself - note I removed the trans = reverse specification from your plot.
Plot 2 just adds back the white tiles on top of the other plot - simple hack which you will often find necessary when wanting to plot certain data points differently.
Note I have added a few minor comments to your code below.
# creating your data frame with better name - df is a base R function and not recommended as example name.
# Also note that I removed the quotation marks in the data frame call - they were not necessary. I also called as.numeric directly.
mydf <- data.frame(x_pos = c("A","A","A","B","B","B","C","C","C"), y_pos = c("X","Y","Z","X","Y","Z","X","Y","Z"), col_var= as.numeric(c(1,2,NA,4,5,6,NA,8,9)), alpha_var = as.numeric(c(7,12,0,3,2,15,0,6,15)))
mydf$col_var_cut <- cut(mydf$col_var, breaks = c(0,3,6,10), labels = c("cat1","cat2", "cat3"))
#Plot
library(tidyverse)
library(RColorBrewer) # you forgot to add this to your reprex
ggplot(mydf, aes (x = x_pos, y = y_pos, fill = col_var_cut, label = col_var)) +
geom_tile(aes(alpha = alpha_var)) +
geom_text() +
scale_fill_manual(values=(brewer.pal(3, "RdYlBu")), na.value="white")
#> Warning: Removed 2 rows containing missing values (geom_text).
# a bit hacky for quick and dirty solution. Note I am using dplyr::filter from the tidyverse
ggplot(mapping = aes(x = x_pos, y = y_pos, fill = col_var_cut, label = col_var)) +
geom_tile(data = filter(mydf, !is.na(col_var))) +
geom_tile(data = filter(mydf, !is.na(col_var)), aes(alpha = alpha_var), fill ="gray29")+
geom_tile(data = filter(mydf, is.na(col_var)), fill = 'white') +
geom_text(data = mydf) +
scale_fill_manual(values = (brewer.pal(3, "RdYlBu"))) +
scale_alpha_continuous("alpha_var", range=c(0,0.7), trans = 'reverse')
#> Warning: Removed 2 rows containing missing values (geom_text).
Created on 2019-07-04 by the reprex package (v0.2.1)
I am trying to change the default fill color from blue to green or red.
Here is the code I am using
Top_pos<- ggplot(Top_10, aes(x=reorder(Term,Cs), y=Cs, fill=pvalue)) +
geom_bar(stat = "identity", colour="black") + coord_flip()
Using the above code, I get the following image. I have no problem with this data but I do not know how to change the fill color.
It's easy to confuse scaling the color and scaling the fill. In the case of geom_bar/geom_col, color changes the borders around the bars while fill changes the colors inside the bars.
You already have the code that's necessary to scale fill color by value: aes(fill = pvalue). The part you're missing is a scale_fill_* command. There are several options; some of the more common for continuous scales are scale_fill_gradient or scale_fill_distiller. Some packages also export palettes and scale functions to make it easy to use them, such as the last example which uses a scale from the rcartocolor package.
scale_fill_gradient lets you set endpoints for a gradient; scale_fill_gradient2 and scale_fill_gradientn let you set multiple midpoints for a gradient.
scale_fill_distiller interpolates ColorBrewer palettes, which were designed for discrete data, into a continuous scale.
library(tidyverse)
set.seed(1234)
Top_10 <- tibble(
Term = letters[1:10],
Cs = runif(10),
pvalue = rnorm(10, mean = 0.05, sd = 0.005)
)
plt <- ggplot(Top_10, aes(x = reorder(Term, Cs), y = Cs, fill = pvalue)) +
geom_col(color = "black") +
coord_flip()
plt + scale_fill_gradient(low = "white", high = "purple")
plt + scale_fill_distiller(palette = "Greens")
plt + rcartocolor::scale_fill_carto_c(palette = "Sunset")
Created on 2018-05-05 by the reprex package (v0.2.0).
Personally, I'm a fan of R Color Brewer. It's got a set of built-in palettes that play well together for qualitative, sequential or diverging data types. Check out colorbrewer2.org for some examples on real-ish data
More generally, and for how to actually code it, you can always add a scale_fill_manual argument. There are some built-ins in ggplot2 for gradients (examples here)
I'm currently working on a very simple data.frame, containing three columns:
x contains x-coordinates of a set of points,
y contains y-coordinates of the set of points, and
weight contains a value associated to each point;
Now, working in ggplot2 I seem to be able to plot contour levels for these data, but i can't manage to find a way to fill the plot according to the variable weight. Here's the code that I used:
ggplot(df, aes(x,y, fill=weight)) +
geom_density_2d() +
coord_fixed(ratio = 1)
You can see that there's no filling whatsoever, sadly.
I've been trying for three days now, and I'm starting to get depressed.
Specifying fill=weight and/or color = weight in the general ggplot call, resulted in nothing. I've tried to use different geoms (tile, raster, polygon...), still nothing. Tried to specify the aes directly into the geom layer, also didn't work.
Tried to convert the object as a ppp but ggplot can't handle them, and also using base-R plotting didn't work. I have honestly no idea of what's wrong!
I'm attaching the first 10 points' data, which is spaced on an irregular grid:
x = c(-0.13397460,-0.31698730,-0.13397460,0.13397460,-0.28867513,-0.13397460,-0.31698730,-0.13397460,-0.28867513,-0.26794919)
y = c(-0.5000000,-0.6830127,-0.5000000,-0.2320508,-0.6547005,-0.5000000,-0.6830127,-0.5000000,-0.6547005,0.0000000)
weight = c(4.799250e-01,5.500250e-01,4.799250e-01,-2.130287e+12,5.798250e-01,4.799250e-01,5.500250e-01,4.799250e-01,5.798250e-01,6.618956e-01)
any advise? The desired output would be something along these lines:
click
Thank you in advance.
From your description geom_density doesn't sound right.
You could try geom_raster:
ggplot(df, aes(x,y, fill = weight)) +
geom_raster() +
coord_fixed(ratio = 1) +
scale_fill_gradientn(colours = rev(rainbow(7)) # colourmap
Here is a second-best using fill=..level... There is a good explanation on ..level.. here.
# load libraries
library(ggplot2)
library(RColorBrewer)
library(ggthemes)
# build your data.frame
df <- data.frame(x=x, y=y, weight=weight)
# build color Palette
myPalette <- colorRampPalette(rev(brewer.pal(11, "Spectral")), space="Lab")
# Plot
ggplot(df, aes(x,y, fill=..level..) ) +
stat_density_2d( bins=11, geom = "polygon") +
scale_fill_gradientn(colours = myPalette(11)) +
theme_minimal() +
coord_fixed(ratio = 1)
I have trolled ggplot2 documentation, Stack and the ggplot2 Google groups email list - but to no avail.
Please can someone tell me how to merge the legends for alpha (opacity) and size? They are titled "(1-val2)" and "val2", respectively.
Normally mapping alpha and size to val2 would automatically merge the axes. However because I'm using "val2" and "1-val2", this does not happen. I have played around with scale_size_continuous and scale_alpha_continuous, but didn't manage to come right.
Here is a MWE:
require(ggplot2)
dummy <- data.frame(x=c(runif(12,5,10)),
y=c(runif(12,5,10)),
val1=c("a","b","c","a","b","c","a","b","c","a","b","c"),
val2=c(0.4,0.6,0.7,0.2,0.8,0.6,0.7,0.2,0.5,0.8,0.4,0.7))
p <- ggplot() +
geom_point(data=dummy, aes(x=x, y=y,color=val1, size=val2, alpha=(1-val2)))
Use the range argument of scale_alpha_continuous to invert the scale:
ggplot() +
geom_point(data=dummy, aes(x=x, y=y,color=val1, size=val2, alpha=val2)) +
scale_alpha_continuous(range = c(1, 0.1))
The trans argument may also be useful here:
ggplot() +
geom_point(data=dummy, aes(x = x, y = y, color = val1, size = val2, alpha = val2)) +
scale_alpha_continuous(trans = "reverse")
The description of the trans argument in ?scale_alpha_continuous and ?continuous_scale is pretty thin. However, you can find some examples here.