I want to use ggplot to show points and lines, but I want there to be two legends - one for the points and one for the lines.
I managed to do this using the below code, but for some reason the 'size' option no longer responds in geom_point and they are stuck at the fairly ugly size you can see in the image
.
Note that I chose stroke = NA because I do not want the points to have a border. The code is below.
Any ideas?
ggplot(data = plot_data) +
geom_point(aes(x = z.1, y = obs, fill = treatcat), alpha = 0.4, shape = 21, stroke = NA, size = 1) +
geom_line(aes(x = z.1, y = under, colour = "True"), linetype = "dashed") +
geom_line(aes(x = z.1, y = crude, colour = "Crude"), size = 1.5) +
scale_fill_manual(name = "Treatment",
values = c("0" = "#F8766D", "1" = "#C77CFF"),
breaks = c("0", "1"),
labels = c("Untreated", "Treated")) +
scale_colour_manual(name = "Model",
values = c("Crude" = "orange", "True" = "black"),
breaks = c("Crude", "True"),
labels = c("Crude", "True")) +
ylim(-30,27.5) +
theme(plot.title = element_text(size = "12")) +
labs(title = "Fitted Values for Crude Model", x = "Z", y = "Y(1)")
Maybe you want two color scales, here a solution with ggnewscale. There are a couple of github packages with similar functionality on the horizon (relayer, and ggh4x), but currently this is the only CRAN option to my knowledge.
As per comment - I am using see::geom_point2 because I also don't like those strokes
library(ggplot2)
library(see)
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) +
geom_point2(aes(color = Petal.Width), alpha = 0.4, size = 10) +
ggnewscale::new_scale_color() +
geom_smooth(aes(color = Species), linetype = "dashed", method = "lm")
Currently, there is a bug in ggplot2 that makes it impossible to change size once stroke = NA (https://github.com/tidyverse/ggplot2/issues/4624). Apprarently, setting 'stroke = 0' also does not eliminate the border.
To do what you want, you need to set set color to 'transparent':
library(ggplot2)
df = data.frame(x=rnorm(100), y=rnorm(100))
ggplot(df, aes(x, y)) + geom_point(shape=21, stroke=0, fill="orange", color="transparent", size=8)
Created on 2021-09-20 by the reprex package (v2.0.1)
Related
I've written this code:
ggplot() +
geom_sf(aes(fill = dat$color_province)) +
theme_void() +
geom_point(data = producer,
aes(x = producer$MX, y = producer$MY), size = 3, col = "green", shape = 17, alpha = 0.6) +
geom_point(data = distribution,
aes(x = distribution$MX, y = distribution$MY), size = 4.5, col = "yellow", shape = 15) +
geom_point(data = retailer,
aes(x = retailer$MX, y = retailer$MY), size = 3, col = "slateblue", shape = 16) +
geom_point(data = Demand,
aes(x = Demand$MX, y = Demand$MY, size = Demand$De), col = "slateblue", shape = 17, alpha = 0.7) +
scale_fill_manual(values = c("#ff3333", "#ffc266"),
name = "Situation")
and now I want to add a legend to identify all points in my plot. How can I do it?
Here's an example on some data that everyone can run, since it uses built-in datasets that come with R. Here, I made color and size be dynamic aesthetics with the name of the series, and then mapped those series values to different aesthetic values using scale_*_manual, where * are the aesthetics you want to vary by series. This generates an automatic legend. By giving each aesthetic the same name ("source" here), ggplot2 knows to combine them into one legend.
(By the way, it's unnecessary and can lead to errors to refer to variables in ggplot2 aesthetics using the form retailer$MY; each geom will assume the variable is within the data frame referred to with data =, so you can just use MY in that case.)
ggplot() +
geom_point(data = mtcars,
aes(x = wt, y = mpg, color = "mtcars", size = "mtcars")) +
geom_point(data = attitude,
aes(x = rating/20, y = complaints/3, color = "attitude", size = "attitude")) +
scale_color_manual(values = c("mtcars" = "slateblue", "attitude" = "red"), name = "source") +
scale_size_manual(values = c("mtcars" = 3, "attitude" = 4.5), name = "source")
I would like to create a raincloud plot. I have successfully done it. But I would like to know if instead of the density curve, I can put a histogram (it's better for my dataset).
This is my code if it can be usefull
ATSC <- ggplot(data = data, aes(y = atsc, x = numlecteur, fill = numlecteur)) +
geom_flat_violin(position = position_nudge(x = .2, y = 0), alpha = .5) +
geom_point(aes(y = atsc, color = numlecteur), position = position_jitter(width = .15), size = .5, alpha = 0.8) +
geom_point(data = sumld, aes(x = numlecteur, y = mean), position = position_nudge(x = 0.25), size = 2.5) +
geom_errorbar(data = sumld, aes(ymin = lower, ymax = upper, y = mean), position = position_nudge(x = 0.25), width = 0) +
guides(fill = FALSE) +
guides(color = FALSE) +
scale_color_brewer(palette = "Spectral") +
scale_y_continuous(breaks=c(0,2,4,6,8,10), labels=c("0","2","4","6","8","10"))+
scale_fill_brewer(palette = "Spectral") +
coord_flip() +
theme_bw() +
expand_limits(y=c(0, 10))+
xlab("Lecteur") + ylab("Age total sans check")+
raincloud_theme
I think we can maybe put the "geom_histogram()" but it doesn't work
Thank you in advance for your help !
(sources : https://peerj.com/preprints/27137v1.pdf
https://neuroconscience.wordpress.com/2018/03/15/introducing-raincloud-plots/)
This is actually not quite easy. There are a few challenges.
geom_histogram is "horizontal by nature", and the custom geom_flat_violin is vertical - as are boxplots. Therefore the final call to coord_flip in that tutorial. In order to combine both, I think best is switch x and y, forget about coord_flip, and use ggstance::geom_boxploth instead.
Creating separate histograms for each category is another challenge. My workaround to create facets and "merge them together".
The histograms are scaled way bigger than the width of the points/boxplots. My workaround scale via after_stat function.
How to nudge the histograms to the right position above Boxplot and points - I am converting the discrete scale to a continuous by mapping a constant numeric to the global y aesthetic, and then using the facet labels for discrete labels.
library(tidyverse)
my_data<-read.csv("https://data.bris.ac.uk/datasets/112g2vkxomjoo1l26vjmvnlexj/2016.08.14_AnxietyPaper_Data%20Sheet.csv")
my_datal <-
my_data %>%
pivot_longer(cols = c("AngerUH", "DisgustUH", "FearUH", "HappyUH"), names_to = "EmotionCondition", values_to = "Sensitivity")
# use y = -... to position boxplot and jitterplot below the histogram
ggplot(data = my_datal, aes(x = Sensitivity, y = -.5, fill = EmotionCondition)) +
# after_stat for scaling
geom_histogram(aes(y = after_stat(count/100)), binwidth = .05, alpha = .8) +
# from ggstance
ggstance::geom_boxploth( width = .1, outlier.shape = NA, alpha = 0.5) +
geom_point(aes(color = EmotionCondition), position = position_jitter(width = .15), size = .5, alpha = 0.8) +
# merged those calls to one
guides(fill = FALSE, color = FALSE) +
# scale_y_continuous(breaks = 1, labels = unique(my_datal$EmotionCondition))
scale_color_brewer(palette = "Spectral") +
scale_fill_brewer(palette = "Spectral") +
# facetting, because each histogram needs its own y
# strip position = left to fake discrete labels in continuous scale
facet_wrap(~EmotionCondition, nrow = 4, scales = "free_y" , strip.position = "left") +
# remove all continuous labels from the y axis
theme(axis.title.y = element_blank(), axis.text.y = element_blank(),
axis.ticks.y = element_blank())
Created on 2021-04-15 by the reprex package (v1.0.0)
I want to use facet_grid with stat_compare_means and have individual scales for y. I thought scale = "free" would take care of it, but it doesn't. Level "B" in my Name factor is not scaled properly.
library(tidyverse)
library(ggpubr)
set.seed(2)
my_comparisons <- list(c("Cond1","Cond2"),
c("Cond2","Cond3"),
c("Cond1","Cond3"))
nrName <- 4
nrCond <- 3
nrValue <- 5
Name <- rep(c("A","B","C","D"),each=nrValue*nrCond)
Condition <- rep(c("Cond1","Cond2","Cond3"),length.out=nrName*nrCond*nrValue)
Score <- c(rnorm(nrValue*nrCond,6,1),rnorm(nrValue*nrCond,0.01,0.01),rnorm(nrValue*nrCond,7,1),rnorm(nrValue*nrCond,7,1))
df <- data.frame(Name = Name, Condition = Condition, Score = Score)
plt <- ggplot(df,
aes(x= Condition,y= Score, fill= Condition))+
#geom_flat_violin(position = position_nudge(x = .2),adjust = 2)+
geom_point(position = position_jitter(width = .15), size = .25)+
geom_boxplot(outlier.shape = NA, alpha = 0.3, width = .1, colour = "BLACK") +
facet_grid(reformulate("Name","."),scales = 'free')+
scale_y_continuous(expand = expansion(mult = c(0, 0.1)))+
stat_compare_means(
comparisons = my_comparisons,
method = "t.test",paired = TRUE,
label.y.npc = 0.1)
print(plt)
I thought it might be related to the labels in stat_compare_means. But removing stat_compare_means yields similar result.
What am I not considering here?
I see my confusion now. As RonakShah pointed out correctly, I use geom_flat_violin from the the PupillometryR in my original code. I wanted to simplify the problem when I wrote the post here which is the reason why I showed the boxplots. If I add the line with the geom_flat_vioilin back in, and use greom_wrap as suggested by Suren, the scale = "free" option doesn't work anymore.
ggplot(df,
aes(x= Condition,y= Score,fill= Condition))+
geom_flat_violin(position = position_nudge(x = .2))+
geom_point(position = position_jitter(width = .15), size = .25)+
geom_boxplot(outlier.shape = NA, alpha = 0.3, width = .1, colour = "BLACK") +
facet_wrap(reformulate("Name","."),scales = 'free',nrow = 1)+
scale_y_continuous(expand = expansion(mult = c(0, 0.1)))
I guess I have to check out the geom_flat_violin function for further debuging.
Instead of facet_grid use facet_wrap for example,
facet_wrap(reformulate("Name","."), scales = 'free', nrow = 1) +
With facet_grid one can not get both x and y scales free; see here https://github.com/tidyverse/ggplot2/issues/1152
I am trying to overlay two scatter plots in ggplot2. The goal is to make the outside part of dots colored according to one variable (6 categories, factor) and the inside filled with a gradient color of another continuous variable (numeric).
I wrote two pieces of code, each works on its own (please see screenshots below).
ggplot(PCA_isotopes_2, aes(x=PC1, y=PC2)) +
theme_classic() +
geom_point(aes(color = factor(subspecies)), shape = 1, size = 2.95, stroke=1, alpha=5/6) +
scale_color_manual(breaks = c("gutturalis", "rg.hybrids", "rt", "rustica", "tg", "tytleri"), values=c("#0066CC", "#9933CC", "#FFCC99", "#CC0000", "#33CC99", "#FFFF00"))
ggplot(PCA_isotopes_2, aes(x=PC1, y=PC2)) +
theme_classic() +
geom_point(aes(color = carbon.ratio), size = 2.88, alpha=5/6) +
scale_colour_gradient(low = "blue", high = "yellow")
When I try to overlay them this way:
p <- ggplot(PCA_isotopes_2, aes(x=PC1, y=PC2)) +
theme_classic() +
geom_point(aes(color = carbon.ratio), size = 2.88, alpha=5/6) +
scale_colour_gradient(low = "blue", high = "yellow")
p + geom_point(aes(color = factor(subspecies)), shape = 1, size = 2.95, stroke=1, alpha=5/6) +
scale_color_manual(breaks = c("gutturalis", "rg.hybrids", "rt", "rustica", "tg", "tytleri"), values=c("#0066CC", "#9933CC", "#FFCC99", "#CC0000", "#33CC99", "#FFFF00"))
I get error messages:
"Scale for 'colour' is already present. Adding another scale for 'colour', which
will replace the existing scale.
Error: Continuous value supplied to discrete scale".
I've spent a couple hours trying to figure out why it doesn't work. I will very appreciate help!
Thanks,
Georgy
In general you can only map an aesthetic once. Here is a workaround that uses a fill aesthetic for the continuous variable as an alternative, with shape = 21. However, I would prefer to map to a different aesthetic, such as shape, entirely, as in the second version.
library(tidyverse)
ggplot(iris, aes(x = Petal.Length, y = Petal.Width)) +
theme_classic() +
geom_point(
mapping = aes(colour = Species),
shape = 1,
size = 3,
stroke = 2,
alpha = 5 / 6
) +
geom_point(
mapping = aes(fill = Sepal.Length, colour = NA),
size = 2.88,
alpha = 5 /6,
shape = 21
) +
scale_fill_gradient(low = "blue", high = "yellow")
library(viridis)
#> Loading required package: viridisLite
ggplot(iris, aes(x = Petal.Length, y = Petal.Width)) +
theme_classic() +
geom_point(
mapping = aes(colour = Sepal.Length, shape = Species),
size = 3,
alpha = 5 / 6
) +
scale_colour_viridis()
Created on 2018-04-19 by the reprex package (v0.2.0).
I have the following ggplot graph with circles representing the observed data and the crosses the mean for each treatment :
d <- data.frame(Number = rnorm(12,100,20),
Treatment = rep(c("A","B","C", "D"), each = 3))
av <- aggregate(d["Number"], d["Treatment"], mean)
ggplot(data = d, aes(y = Number, x = Treatment)) +
geom_point(shape = 1, size = 6, color = "grey50") +
geom_point(data=av, shape = 4) +
theme_bw()
I would like to add a legend with the exact same symbols on top of the graphs but I'm a bit lost... I use aes to force the creation of legend and then try to modify it with manual scales but the result is not convincing. I would like to have one grey circle of size 6. That sounds also quite complicated for such a basic thing ... There is probably an easyier solution.
ggplot(data = d, aes(y = Number, x = Treatment)) +
geom_point(aes(shape = "1", size = "6", color = "grey50")) +
geom_point(data=av, aes(shape = "4")) +
theme_bw() +
scale_shape_manual(name = "", values = c(1,4), labels = c("observed values", "mean")) +
scale_size_manual(name = "", values = c(6,1), labels = c("observed values", "mean")) +
scale_color_manual(name = "", values = c("grey50","black"),
labels = c("observed values", "mean")) +
theme(legend.position = "top",
legend.key = element_rect(color = NA))
http://imagizer.imageshack.us/v2/320x240q90/842/4pgj.png
The ggplot2 way would be combining everything into a single data.frame like this:
av$Aggregated <- "mean"
d$Aggregated <- "observed value"
d <- rbind(d, av)
ggplot(data = d, aes(y = Number, x = Treatment,
shape=Aggregated, size=Aggregated, colour=Aggregated)) +
geom_point()
And than customize using manual scales and themes.