I want to specific the shape of three kinds of points in my plot using ggplot2. However, no matter how I change the shape numbers, it doesn't work, the shapes of points been constantly set automatically.
Here is my code (the shape numbers are in the first line):
shape <- c("min"="1","max"="2",mean="3")
fill <- c("Rate"="#25c25b")
ggplot (data, aes(x=order))+
geom_rect(aes(xmin=order-0.1, xmax=order+0.1, ymin = min, ymax=max), alpha=0, color="black")+
geom_bar(aes(y=rate, fill="Rate"),stat="identity", alpha=0.3, width=0.5)+
geom_point(aes(y=min, shape="min"), size=5)+
geom_point(aes(y=mean, shape="mean"), size=5)+
geom_point(aes(y=max, shape="max"), size=5)+
labs(shape = "F0", fill = "Rate")
To change the shape of points you need to use scale_shape_manual() and provide argument values= with shapes you need.
+ scale_shape_manual(values=c("min"=1,"max"=2,"mean"=3))
Related
I want to draw a dot plot with horizontal lines by groups.
The df object store the points and the df.line object stores the line I want to add to the dot plot. The horizontal lines are not the mean/median value of points, they are some standards I want to show in this figure.
I tried gome_hline, geom_line, geom_errorbar, and stat_summary. but none of them work as I want.
Could anyone teach me how to do it?
library(ggplot2)
library(tidytext)
set.seed(42)
df=data.frame(site=c(rep("a",5),rep("b",5),rep("c",5)),
sample=c(1:5,1:5,1:5),
value=c(runif(5, min=0.54, max=0.56),runif(5, min=0.52, max=0.6),runif(5,
min=0.3, max=0.4)),
condition=c(rep("c1",5),rep("c2",5),rep("c2",5)))
df.line=data.frame(site=c("a","b","c"),standard=c(0.55,0.4,0.53))
ggplot(df)+
geom_point(aes(x=tidytext::reorder_within(site,value,condition,fun=mean),
y=value))+
facet_grid(~condition,space="free_x",scales = "free_x")+
scale_x_reordered()
First, merge df and df.line together. Next, move the main aes() call to ggplot so it can be used later. Then use stat_summary:
library(dplyr)
merge(df,df.line) %>%
ggplot(aes(x=tidytext::reorder_within(site,value,condition,fun=mean),
y=value))+
geom_point()+
stat_summary(aes(y = standard, ymax = after_stat(y), ymin = after_stat(y)),
fun = mean, geom = "errorbar", color = "red", width = 0.3) +
facet_grid(~condition,space="free_x",scales = "free_x")+
scale_x_reordered()
I am trying to create some maps in R utilising ggplot2. I've reached a point where I have the final map I want spatially, but need to change the shape and colour of the points according to categorial factors.
The data frame is called genAQ in this context. Each row contains longitude and latitude, quality (high/low) and species (3 sp). Eventually, I would like the point colour to be in accordance with species, and the point shape to be in accordance with quality.
#correct spatial map, but all points are black. This code works perfectly.
ggplot(data=world) +
geom_sf() +
geom_point(data=genAQ, aes(x=Lon, y=Lat), size=1,
shape = 19, col = "black") +
geom_polygon(data=lakes10, aes(long, lat, group = group), fill="lightblue") +
coord_sf(xlim = c(133.75, 140.52), ylim = c(-26.75, -31.30), expand=F)
Now I try to change the colour, utilising species as a factor.
If I were coding using the plot function, I would write it as
plot(genAQ$Lat~genAQ$Lon, pch=19, col=genAQ$Species).
Using this same principle, I try to apply it to the initial code which works.
ggplot(data=world) +
geom_sf() +
geom_point(data=genAQ, aes(x=Lon, y=Lat), size=1,
shape = 19, col = genAQ$Species) +
geom_polygon(data=lakes10, aes(long, lat, group = group), fill="lightblue") +
coord_sf(xlim = c(133.75, 140.52), ylim = c(-26.75, -31.30), expand=F)
It comes back with an error:
Error in grDevices::col2rgb(colour, TRUE) :
invalid color name 'Amytornis modestus indulkanna'.
So clearly ggplot does not understand the same language I'm using in the plot() function, as it's still trying to read the colour as a colour, rather than a categorical factor. I've tried other methods I've seen on StackOverflow, but I can't seem to find an answer for a seemly simple problem.
I'm creating a plot with ggplot that uses colored points, vertical lines, and horizontal lines to display the data. Ideally, I'd like to use two different color or linetype scales for the geom_vline and geom_hline layers, but ggplot discourages/disallows multiple variables mapped to the same aesthetic.
# Create example data
library(tidyverse)
library(lubridate)
set.seed(1234)
example.df <- data_frame(dt = seq(ymd("2016-01-01"), ymd("2016-12-31"), by="1 day"),
value = rnorm(366),
grp = sample(LETTERS[1:3], 366, replace=TRUE))
date.lines <- data_frame(dt = ymd(c("2016-04-01", "2016-10-31")),
dt.label = c("April Fools'", "Halloween"))
value.lines <- data_frame(value = c(-1, 1),
value.label = c("Threshold 1", "Threshold 2"))
If I set linetype aesthetics for both geom_*lines, they get put in the
linetype legend together, which doesn't necessarily make logical sense
ggplot(example.df, aes(x=dt, y=value, colour=grp)) +
geom_hline(data=value.lines, aes(yintercept=value, linetype=value.label)) +
geom_vline(data=date.lines, aes(xintercept=as.numeric(dt), linetype=dt.label)) +
geom_point(size=1) +
scale_x_date() +
theme_minimal()
Alternatively, I could set one of the lines to use a colour aesthetic,
but then that again puts the legend lines in an illogical legend
grouping
ggplot(example.df, aes(x=dt, y=value, colour=grp)) +
geom_hline(data=value.lines, aes(yintercept=value, colour=value.label)) +
geom_vline(data=date.lines, aes(xintercept=as.numeric(dt), linetype=dt.label)) +
geom_point(size=1) +
scale_x_date() +
theme_minimal()
The only partial solution I've found is to use a fill aesthetic instead
of colour in geom_pointand setting shape=21 to use a fillable shape,
but that forces a black border around the points. I can get rid of the
border by manually setting color="white, but then the white border
covers up points. If I set colour=NA, no points are plotted.
ggplot(example.df, aes(x=dt, y=value, fill=grp)) +
geom_hline(data=value.lines, aes(yintercept=value, colour=value.label)) +
geom_vline(data=date.lines, aes(xintercept=as.numeric(dt), linetype=dt.label)) +
geom_point(shape=21, size=2, colour="white") +
scale_x_date() +
theme_minimal()
This might be a case where ggplot's "you can't have two variables mapped
to the same aesthetic" rule can/should be broken, but I can't figure out clean way around it. Using fill with geom_point shows the most promise, but there's no way to remove the point borders.
Any ideas for plotting two different color or linetype aesthetics here?
I have got a map with a legend gradient and I would like to add a box for the NA values. My question is really similar to this one and this one. Also I have read this topic, but I can't find a "nice" solution somewhere or maybe there isn't any?
Here is an reproducible example:
library(ggplot2)
map <- map_data("world")
map$value <- setNames(sample(-50:50, length(unique(map$region)), TRUE),
unique(map$region))[map$region]
map[map$region == "Russia", "value"] <- NA
ggplot() +
geom_polygon(data = map,
aes(long, lat, group = group, fill = value)) +
scale_fill_gradient2(low = "brown3", mid = "cornsilk1", high = "turquoise4",
limits = c(-50, 50),
na.value = "black")
So I would like to add a black box for the NA value for Russia. I know, I can replace the NA's by a number, so it will appear in the gradient and I think, I can write a workaround like the following, but all this workarounds do not seem like a pretty solution for me and also I would like to avoid "senseless" warnings:
ggplot() +
geom_polygon(data = map,
aes(long, lat, group = group, fill = value)) +
scale_fill_gradient2(low = "brown3", mid = "cornsilk1", high = "turquoise4",
limits = c(-50, 50),
na.value = "black") +
geom_point(aes(x = -100, y = -50, size = "NA"), shape = NA, colour = "black") +
guides(size = guide_legend("NA", override.aes = list(shape = 15, size = 10)))
Warning messages:
1: Using size for a discrete variable is not advised.
2: Removed 1 rows containing missing values (geom_point).
One approach is to split your value variable into a discrete scale. I have done this using cut(). You can then use a discrete color scale where "NA" is one of the distinct colors labels. I have used scale_fill_brewer(), but there are other ways to do this.
map$discrete_value = cut(map$value, breaks=seq(from=-50, to=50, length.out=8))
p = ggplot() +
geom_polygon(data=map, aes(long, lat, group=group, fill=discrete_value)) +
scale_fill_brewer(palette="RdYlBu", na.value="black") +
coord_quickmap()
ggsave("map.png", plot=p, width=10, height=5, dpi=150)
Another solution
Because the original poster said they need to retain the color gradient scale and the colorbar-style legend, I am posting another possible solution. It has 3 components:
We need to trick ggplot into drawing a separate color scale by using aes() to map something to color. I mapped a column of empty strings using aes(colour="").
To ensure that we do not draw a colored boundary around each polygon, I specified a manual color scale with a single possible value, NA.
Finally, guides() along with override.aes is used to ensure the new color legend is drawn as the correct color.
p2 = ggplot() +
geom_polygon(data=map, aes(long, lat, group=group, fill=value, colour="")) +
scale_fill_gradient2(low="brown3", mid="cornsilk1", high="turquoise4",
limits=c(-50, 50), na.value="black") +
scale_colour_manual(values=NA) +
guides(colour=guide_legend("No data", override.aes=list(colour="black")))
ggsave("map2.png", plot=p2, width=10, height=5, dpi=150)
It's possible, but I did it years ago. You can't use guides. You have to set individually the continuous scale for the values as well as the discrete scale for the NAs. This is what the error is telling you and this is how ggplot2 works. Did you try using both scale_continuous and scale_discrete since your set up is rather awkward, instead of simply using guides which is basically used for simple plot designs?
I am trying to make a boxplot filled by a binary variable, with a facet grid. I also want to have jitter on top of the boxplots, but without getting them confused with the outliers. In order to fix this, I have added colour to the jitter, but by doing so, they meld in with the already coloured boxplots, as they are the same colour.
I really want to keep the colours the same, so is there a way to add borders to the jitter (or is there a different way to fix the outlier problem)?
Example code:
plot <- ggplot(mpg, aes(class, hwy))+
geom_boxplot(aes(fill = drv))+
geom_jitter(width = .3, aes(colour =drv))
# facet_grid(. ~some_binary_variable, scales="free")
You can use a filled plotting symbol (21:25, cf. ?pch) and then use a white border to differentiate the points:
ggplot(mpg, aes(class, hwy))+
geom_boxplot(aes(fill = drv))+
geom_jitter(width = .3, aes(fill = drv), shape = 21, color = "white")