ggplot2 geom_point alpha different in plot to legend - r

I have something strange in my plot which I can't figure out. It seems like the transparency of the bubbles in my plot are different to the transparency of those in the legend.
I've found it challenging to provide a reprex for this, so I'm hoping just the code is okay:
ggplot() + geom_polygon(data = all.shp, aes(x = long, y = lat, group=group),
color = "grey", size = 0.3,fill = NA) +
geom_point(data=substation_results, aes(x=Easting, y=Northing, size=factor(Population),
colour=factor(Population), fill = NA), alpha=0.5) +
coord_equal() +
scale_fill_brewer(palette="Spectral", name =
expression('Voltage\nInstability\nZones')) +
theme(axis.text = element_blank(), axis.ticks = element_blank(), axis.title = element_blank(),
legend.position = "right") +
guides(fill = guide_legend(reverse = FALSE)) +
labs(title = "(A) Population Served\nPer Substation") +
scale_colour_manual(name = "Population\nServed Per\nSubstation\n(Million)",
labels = c("<0.15", "0.15-0.3", "0.3-0.45", "0.45-0.6",
"0.6-0.75", "0.75-0.9",">0.9"),
values = c("skyblue4", "blue", "green", "yellow", "orange", "red", "brown")) +
scale_size_manual(name = "Population\nServed Per\nSubstation\n(Million)",
labels = c("<0.15", "0.15-0.3", "0.3-0.45", "0.45-0.6",
"0.6-0.75", "0.75-0.9",">0.9"),
values = c(1, 2, 3, 4, 5, 6, 7))
This is the image of the plot. You can see the colour of the bubbles and the legend are completely different. Importantly, changing the alpha in geom_point does not change the difference:

I resolved the issue by removing duplicate observations using:
transformer_node_count <- unique(transformer_node_count)
and achieving the desired output:

Related

ggplot2: grouping legend items by a variable for combined geom_path and geom_point

I have a connected scatterplot using geom_path and geom_point. I currently have the lines connecting the points by a grouping variable (Species_ordered) and each level of that variable symbolized by a different shape. I have another grouping variable (Type) which has two levels. I have colored the lines and points based on Type, but I also want the symbols in the legend to be grouped by Type, with labels. Something like this:
Sample
Native:
[] label
[] label
[] label
Non-Native:
[] label
[] label
[] label
I currently have this code for a related plot which successfully combined the points and lines into a single legend (thanks to help on this question).
ggplot(great_hollow, aes(x = d15N, y = Sample_ordered), color =
Species_ordered) +
geom_path(aes(group = Species_ordered, colour = Species_ordered)) +
geom_point(aes(shape = Species_ordered, fill = Species_ordered),
colour = "black", size = 3) +
scale_shape_manual(values = c(21, 22, 24, 21, 23, 25)) +
facet_wrap(~Type, scales = "fixed") +
ggtitle(expression(paste(delta^{15},
"N Values by Site and Trophic Level"))) +
scale_x_continuous(expression(paste(delta^{15}, "N (\u2030 VS air)"))) +
scale_y_discrete(limits=rev) +
labs(color = "Sample", shape = "Sample", fill = "Sample") +
theme_bw() +
theme(plot.title = element_text(hjust = 0.5),
axis.title.y = element_blank(),
plot.background = element_rect(color = 1, linewidth = 1),
plot.margin = margin(t = 10, r = 10, b = 10, l = 10))
The resulting plot:
I'm trying to create a plot like it where the legend is still combined but the plot is not faceted, there are only two colors (by Type), and the different levels of Species_ordered are grouped by Type in the legend.
This is what I have so far based on this question, using ggnewscale:
ggplot(great_hollow, aes(x = d15N, y = Sample_ordered), color = Type) +
geom_path(aes(group = Species_ordered, colour = Type)) +
geom_point(aes(shape = Species_ordered, fill = Type),
colour = "black", size = 3) +
scale_shape_manual(values = c(21, 22, 24, 21, 23, 25)) +
scale_fill_manual(name = "Native",
values = c("blue", "red"),
breaks = great_hollow$Type[c(1,5,6)],
labels = great_hollow$Species_ordered[c(1,5,6)],
guide = guide_legend(title.position = "top", order = 1))
+
new_scale_fill() +
geom_path(aes(group = Species_ordered, colour = Type)) +
scale_colour_manual(values = c("blue", "red")) +
geom_point(aes(shape = Species_ordered, fill = Type), colour = "black",
size = 3) +
scale_fill_manual(name = "Non-Native",
values = c("blue", "red"),
breaks = great_hollow$Type[c(2:4)],
labels = great_hollow$Species_ordered[c(2:4)],
guide = guide_legend(title.position = "top", order = 2))
+
scale_colour_manual(values = c("blue", "red")) +
ggtitle(expression(paste(delta^{15},
"N Values by Site and Trophic Level"))) +
scale_x_continuous(expression(paste(delta^{15}, "N (\u2030 VS air)"))) +
scale_y_discrete(limits=rev) +
labs(colour = "Sample", shape = "Sample", fill = "Sample") +
theme_bw() +
theme(plot.title = element_text(hjust = 0.5),
axis.title.y = element_blank(),
plot.background = element_rect(color = 1, linewidth = 1),
plot.margin = margin(t = 10, r = 10, b = 10, l = 10))
The resulting plot:
To be perfectly honest I can't quite figure out what the answerer was doing with "breaks" inside scale_fill_manual() so my issue might be there. I'm not sure why the "Native" and "Non-Native" legend groups appear by themselves and not integrated with the other legends or why they each only show one of the three labels from Species_ordered. I'm also not sure why the red points are switched to grey.
------ EDIT ------
After further digging I've made some progress. I was able to fix the mismatched coloring and merge the legends, but the legend does not show the line through the shape like it did in my first graph. I've also managed to separate the legend items into columns, but I still can't figure out how to sort them into those columns by Type or add subheadings.
ggplot(great_hollow, aes(x = d15N, y = Sample_ordered), colour = Type) +
geom_path(aes(group = Species_ordered, colour = Type)) +
scale_colour_manual(values = c("blue", "red")) +
geom_point(aes(shape = Species_ordered, fill = Type), colour = "black", size = 3) +
scale_shape_manual(name = "Species",
labels = great_hollow$Species_ordered,
values = c(21, 22, 24, 21, 23, 25)) +
scale_fill_manual(name = "Species",
labels = great_hollow$Species_ordered,
values = c("blue", "red"),
guide = "none",
aesthetics = c("colour", "fill")) +
guides(shape = guide_legend(ncol = 2, override.aes = list(fill = c("blue", "red", "red", "red", "blue", "blue")))) +
ggtitle(expression(paste(delta^{15},"N Values by Site and Trophic Level"))) +
scale_x_continuous(expression(paste(delta^{15}, "N (\u2030 VS air)"))) +
scale_y_discrete(limits=rev) +
theme_bw() +
theme(axis.title.y = element_blank())
And the resulting graph: Colors and columns mostly fixed, no subheadings

make a common legend and include unique legend attributes

I am attempting to combine a legend for two plots with a shared blue line and unique bar colors (read and yellow). When plotting the code below only two of the three colored id's show up in the combined legend (red and blue) but I want the third color to show up as well in the combined legend.
For example
red as beaver temp1
yellow as beaver temp2
blue as line
Here the line is a stand in for what I am using for a moving average. I don't think facet wrapping this will work as there are additional variable parameters in my code (i.e. scale_y_continuous that have different secondary axis scales) but below is a reproducible example of the basic idea.
library(datasets)
library(ggplot2)
library(cowplot)
data(beavers)
colour <- c("bevTemp1" = "red", "line" = "blue", "bevTemp2" = "yellow" )
bev1 <- ggplot(beaver1, aes(x=time, y = temp)) +
geom_bar(stat = "identity", aes(colour = "bevTemp1"), fill = "red")+
coord_cartesian(ylim = c(35, 38)) +
geom_line(size = 1.5, aes(color = "line"))+
scale_color_manual(values = colour,
guide = guide_legend(override.aes = list(
border=c(NA, NA),
fill=c("red","blue"))))+
theme(legend.title = element_blank(), legend.position = "none")
bev2<- ggplot(beaver2, aes(x=time, y = temp)) +
geom_bar(stat = "identity", aes(colour = "bevTemp2"), fill = "yellow")+
coord_cartesian(ylim = c(35, 38)) +
geom_line(size = 1.5, aes(color = "line"))+
scale_color_manual(values = colour,
guide = guide_legend(override.aes = list(
border=c(NA, NA),
fill=c("yellow","blue"))))+
theme(legend.title = element_blank(), legend.position = "none")
cowplot::plot_grid(
cowplot::plot_grid(
bev1 ,
bev2,
align = 'h'),
cowplot::get_legend(bev1 + theme(legend.position = "bottom")),
nrow = 2, rel_heights = c(4, 1))
Suggestions...
You could build a dummy plot just to get the desired legend and add it to the final plot. I would also suggest using the line legend for the geom_line.
library(ggplot2)
# Create dummy data
df <- data.frame(class = c("bevTemp1","bevTemp2"),
x = 1:2,
y = 2:3)
# Create dummy plot just to extract the desired legend
p1<- ggplot(df, aes(x=x,y=y)) +
geom_col(aes(fill = class))+
geom_line(aes(col = "line"), size = 1.5)+
scale_fill_manual(values = c("red","yellow")) +
scale_color_manual(values = "blue")+
theme(legend.title = element_blank())
cowplot::plot_grid(
cowplot::plot_grid(
bev1 ,
bev2,
align = 'h'),
# Add the legend of the dummy plot
cowplot::get_legend(p1 + theme(legend.position = "bottom")),
nrow = 2, rel_heights = c(4, 1))
get_legend just retrieves the legend from the plot passed to this function, here bev1. So you need to also show bev2Temp in the legend of plot 1. You can add an additional id column to your dataset, make it a factor variable but in both datasets include bevTemp1/bevTemp2 as levels. In ggplot in scale_fill_manual, if you set drop = FALSE, all levels are shown:
library(datasets)
library(ggplot2)
library(cowplot)
data(beavers)
colour <- c("bevTemp1" = "red", "bevTemp2" = "yellow")
beaver1$id <- "bevTemp1"
beaver1$id <- factor(beaver1$id, levels = c("bevTemp1", "bevTemp2"))
beaver2$id <- "bevTemp2"
beaver2$id <- factor(beaver2$id, levels = c("bevTemp1", "bevTemp2"))
bev1 <- ggplot(beaver1, aes(x=time, y = temp, fill = id)) +
geom_bar(stat = "identity")+
coord_cartesian(ylim = c(35, 38)) +
geom_line(size = 1.5, aes(color = "line"))+
theme(legend.title = element_blank(), legend.position = "none") +
scale_fill_manual(values = c("bevTemp1" = "red", "bevTemp2" = "yellow"),
drop = FALSE) +
scale_colour_manual(values = c("line" = "blue"))
bev2<- ggplot(beaver2, aes(x=time, y = temp, fill = id)) +
geom_bar(stat = "identity")+
coord_cartesian(ylim = c(35, 38)) +
geom_line(size = 1.5, aes(color = "line"))+
theme(legend.title = element_blank(), legend.position = "none") +
scale_fill_manual(values = c("bevTemp1" = "red", "bevTemp2" = "yellow"),
drop = FALSE) +
scale_colour_manual(values = c("line" = "blue"))
cowplot::plot_grid(
cowplot::plot_grid(
bev1 ,
bev2,
align = 'h'),
cowplot::get_legend(bev1 + theme(legend.position = "bottom")),
nrow = 2, rel_heights = c(4, 1))

ggplot2 scale_fill_gradient() function not changing point colors R

I'm using ggplot2 in R to create maps. In the past, I have been able to successfully use the scale_fill_gradient() function to control geom_point fills. However, when I run the code below (with example table provided), I simply get a map of all black points. The legend appears correct, but the points never change color. I think my desired variable is not mapping to the fill aesthetic, but I cannot figure out why. Thank you in advance!
(if it matters, I am using tibble package to define tables)
table = tibble(long = c(15.28, 15.29, 15.3, 15.31, 15.32), lat = c(-4.4, -4.39, -4.38, -4.37, -4.36), consumption = c(NA, 3, 54, 6, 8))
mapping = aes_string(x = 'long', y = 'lat', fill = 'consumption')
# define breaks, limits, colors
low = 'seashell'
high = 'tan3'
breaks = c(0, max(na.omit(table)[['consumption']]))
limits = breaks
# plot
p <- ggplot() +
# points
geom_point(mapping = mapping, data = table, alpha = 0.7, size = 4) +
# point colors
scale_fill_gradient(low = low, high = high, na.value = 'darkgrey', guide = 'colorbar', aesthetics = 'fill'
, breaks = breaks, limits = limits) +
# title
ggtitle('consumption') +
# title formatting
theme(plot.title = element_text(color = "red", size = 10, face = "bold", hjust=0),
legend.position="bottom",
legend.text=element_text(size=9),
legend.title=element_text(size=9)) +
# legend
guides(fill=guide_colorbar(title='consumption')) +
# get rid of axes, etc.
theme(axis.line = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank()) +
xlab('') +
ylab('') +
# make legend correct
theme(legend.box = 'vertical') +
# add max/min corresponding to map
xlim(c(15.28, 15.38)) +
ylim(c(-4.41, -4.30))
As mentioned in the comments you have to change the fill to color. Here is how I achieved it:
library(tidyverse)
table = tibble(long = c(15.28, 15.29, 15.3, 15.31, 15.32), lat = c(-4.4, -4.39, -4.38, -4.37, -4.36), consumption = c(NA, 3, 54, 6, 8))
##Changed here to color
mapping = aes_string(x = 'long', y = 'lat', color = 'consumption')
# define breaks, limits, colors
low = 'seashell'
high = 'tan3'
breaks = c(0, max(na.omit(table)[['consumption']]))
limits = breaks
# plot
ggplot() +
# points
geom_point(mapping = mapping,
data = table, alpha = 0.7, size = 4) +
# point colors
#Change here to aesthetics = color
scale_color_gradient(low = low, high = high, na.value = 'darkgrey', guide = 'colorbar', aesthetics = 'color'
, breaks = breaks, limits = limits) +
# title
ggtitle('consumption') +
# title formatting
theme(plot.title = element_text(color = "red", size = 10, face = "bold", hjust=0),
legend.position="bottom",
legend.text=element_text(size=9),
legend.title=element_text(size=9)) +
# legend
guides(fill=guide_colorbar(title='consumption')) +
# get rid of axes, etc.
theme(axis.line = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank()) +
xlab('') +
ylab('') +
# make legend correct
theme(legend.box = 'vertical') +
# add max/min corresponding to map
xlim(c(15.28, 15.38)) +
ylim(c(-4.41, -4.30))

ggMarginal ignores choord_cartesian. How to change marginal scales?

I'm trying to plot a 2D density plot with ggplot, with added marginal histograms. Problem is that the polygon rendering is stupid and needs to be given extra padding to render values outside your axis limits (e.g. in this case I set limits between 0 and 1, because values outside this range have no physical meaning). I still want the density estimate though, because often it's much cleaner than a blocky 2D heatmap.
Is there a way around this problem, besides scrapping ggMarginal entirely and spending another 50 lines of code trying to align histograms?
Unsightly lines:
Now rendering works, but ggMarginal ignores choord_cartesian(), which demolishes the plot:
Data here:
http://pasted.co/b581605a
dataset <- read.csv("~/Desktop/dataset.csv")
library(ggplot2)
library(ggthemes)
library(ggExtra)
plot_center <- ggplot(data = dataset, aes(x = E,
y = S)) +
stat_density2d(aes(fill=..level..),
bins= 8,
geom="polygon",
col = "black",
alpha = 0.5) +
scale_fill_continuous(low = "yellow",
high = "red") +
scale_x_continuous(limits = c(-1,2)) + # Render padding for polygon
scale_y_continuous(limits = c(-1,2)) + #
coord_cartesian(ylim = c(0, 1),
xlim = c(0, 1)) +
theme_tufte(base_size = 15, base_family = "Roboto") +
theme(axis.text = element_text(color = "black"),
panel.border = element_rect(colour = "black", fill=NA, size=1),
legend.text = element_text(size = 12, family = "Roboto"),
legend.title = element_blank(),
legend.position = "none")
ggMarginal(plot_center,
type = "histogram",
col = "black",
fill = "orange",
margins = "both")
You can solve this problem by using xlim() and ylim() instead of coord_cartesian.
dataset <- read.csv("~/Desktop/dataset.csv")
library(ggplot2)
library(ggthemes)
library(ggExtra)
plot_center <- ggplot(data = dataset, aes(x = E,
y = S)) +
stat_density2d(aes(fill=..level..),
bins= 8,
geom="polygon",
col = "black",
alpha = 0.5) +
scale_fill_continuous(low = "yellow",
high = "red") +
scale_x_continuous(limits = c(-1,2)) + # Render padding for polygon
scale_y_continuous(limits = c(-1,2)) + #
xlim(c(0,1)) +
ylim(c(0,1)) +
theme_tufte(base_size = 15, base_family = "Roboto") +
theme(axis.text = element_text(color = "black"),
panel.border = element_rect(colour = "black", fill=NA, size=1),
legend.text = element_text(size = 12, family = "Roboto"),
legend.title = element_blank(),
legend.position = "none")
ggMarginal(plot_center,
type = "histogram",
col = "black",
fill = "orange",
margins = "both")

ggplot2: Adjust legend symbols in overlayed plot

I need to create a plot, in which a histogram gets overlayed by a density. Here is my result so far using some example data:
library("ggplot2")
set.seed(1234)
a <- round(rnorm(10000, 5, 5), 0)
b <- rnorm(10000, 5, 7)
df <- data.frame(a, b)
ggplot(df) +
geom_histogram(aes(x = a, y = ..density.., col = "histogram", linetype = "histogram"), fill = "blue") +
stat_density(aes(x = b, y = ..density.., col = "density", linetype = "density"), geom = "line") +
scale_color_manual(values = c("red", "white"),
breaks = c("density", "histogram")) +
scale_linetype_manual(values = c("solid", "solid")) +
theme(legend.title = element_blank(),
legend.position = c(.75, .75),
legend.text = element_text(size = 15))
Unfortunately I can not figure out how I can change the symbols in the legend properly. The first symbol should be a relatively thick red line and the second symbol should be a blue box without the white line in the middle.
Based on some internet research, I tried to change different things in scale_linetype_manual and further I tried to use override.aes, but I could not figure out how I would have to use it in this specific case.
EDIT - Here is the best solution based on the very helpful answers below.
ggplot(df) +
geom_histogram(aes(x = a, y = ..density.., linetype = "histogram"),
fill = "blue",
# I added the following 2 lines to keep the white colour arround the histogram.
col = "white") +
scale_linetype_manual(values = c("solid", "solid")) +
stat_density(aes(x = b, y = ..density.., linetype = "density"),
geom = "line", color = "red") +
theme(legend.title = element_blank(),
legend.position = c(.75, .75),
legend.text = element_text(size = 15),
legend.key = element_blank()) +
guides(linetype = guide_legend(override.aes = list(linetype = c(1, 0),
fill = c("white", "blue"),
size = c(1.5, 1.5))))
As you thought, most of the work can be done via override.aes for linetype.
Note I removed color from the aes of both layers to avoid some trouble I was having with the legend box outline. Doing this also avoids the need for the scale_*_* function calls. To set the color of the density line I used color outside of aes.
In override.aes I set the linetype to be solid or blank, the fill to be either white or blue, and the size to be 2 or 0 for the density box and histogram box, respectively.
ggplot(df) +
geom_histogram(aes(x = a, y = ..density.., linetype = "histogram"), fill = "blue") +
stat_density(aes(x = b, y = ..density.., linetype = "density"), geom = "line", color = "red") +
theme(legend.title = element_blank(),
legend.position = c(.75, .75),
legend.text = element_text(size = 15),
legend.key = element_blank()) +
guides(linetype = guide_legend(override.aes = list(linetype = c(1, 0),
fill = c("white", "blue"),
size = c(2, 0))))
The fill and colour aesthetics are labelled by histogram and density respectively, and their values set using scale_*_manual. Doing so maps directly to the desired legend without needing any overrides.
ggplot(df) +
geom_histogram(aes(x = a, y = ..density.., fill = "histogram")) +
stat_density(aes(x = b, y = ..density.., colour="density"), geom = "line") +
scale_fill_manual(values = c("blue")) +
scale_colour_manual(values = c("red")) +
labs(fill="", colour="") +
theme(legend.title = element_blank(),
legend.position = c(.75, .75),
legend.box.just = "left",
legend.background = element_rect(fill=NULL),
legend.key = element_rect(fill=NULL),
legend.text = element_text(size = 15))

Resources