ggplot(data = results, aes(x = inst, y = value, group = inst)) +
geom_boxplot() +
facet_wrap(~color) +
#geom_line(data = mean,
#mapping = aes(x = inst, y = average, group = 1))
theme_bw()
When I run the code above with the code line commented, it runs and gives the graph below but I want a joining mean lines on the boxplots based on its own color category for each group in facet wraps. Any ideas how can I do that?
Your code is generally correct (though you'll want to add color = color to the aes() specification in geom_line()), so I suspect your mean dataset isn't set up correctly. Do you have means grouped by both your x axis and faceting variable? Using ggplot2::mpg as an example:
library(dplyr) # >= v1.1.0
library(ggplot2)
mean_dat <- summarize(mpg, average = mean(hwy), .by = c(cyl, drv))
ggplot(mpg, aes(factor(cyl), hwy)) +
geom_boxplot() +
geom_line(
data = mean_dat,
aes(y = average, group = 1, color = drv),
linewidth = 1.5,
show.legend = FALSE
) +
facet_wrap(~drv) +
theme_bw()
Alternatively, you could use stat = "summary" and not have to create a means dataframe at all:
ggplot(mpg, aes(factor(cyl), hwy)) +
geom_boxplot() +
geom_line(
aes(group = 1, color = drv),
stat = "summary",
linewidth = 1.5,
show.legend = FALSE
) +
facet_wrap(~drv) +
theme_bw()
# same result as above
Related
I have the current code
ggplot(data = niveles[niveles$departamento=="CUNDINAMARCA" &
niveles$prueba=="MATEMÁTICAS" &
!is.na(niveles$nivel),]) +
geom_bar(stat="identity", position = position_dodge(),
aes(x = año, y = desempeño, fill = nivel)) +
geom_point(data = niveles[niveles$prueba=="MATEMÁTICAS" &
niveles$departamento=="COLOMBIA" &
!is.na(niveles$nivel),], shape = 24,
aes(x = año, y = desempeño, group = nivel, fill = "blue"))
which gives me the following plot:
However, I was hoping to get each one of the "points" withing its corresponding category of the "niveles" variable. Does anyone know how I can do that?
You can dodge points the same way as you dodge bars using position=position_dodge(). However, you need to add a width argument specifying how much to "dodge". A value of 1 should correspond with the dodged bars. You also have an unknown "blue" category in the legend. That's because the fill argument should appear outside the aesthetic (aes)
I also think you should subset the data first instead of doing all that within the ggplot command.
An alternative is to facet by department (see option 2 below).
But first to dodge the points.
Option 1: Subsetting
Create a subset for prueba and non-missing for nivel:
MATH <- niveles[niveles$prueba=="MATEMÁTICAS" & !is.na(niveles$nivel),]
Create subsets for each department:
CUNDINAMARCA <- MATH[MATH$departamento=="CUNDINAMARCA",]
COLOMBIA <- MATH[MATH$departamento=="CUNDINAMARCA",]
Then make your graph:
ggplot(data = CUNDINAMARCA) +
geom_bar(stat="identity", position = position_dodge(),
aes(x = año, y = desempeño, fill = nivel)) +
geom_point(data = COLOMBIA, shape = 24,
position = position_dodge(width=1), # You need this to align points with bars
aes(x = año, y = desempeño, group = nivel), fill = "blue")
I can't test it on your data but I used the mtcars dataset as an example.
mtcars <- mtcars %>%
mutate(gear=factor(gear), cyl=factor(cyl))
VS0 <- mtcars[mtcars$vs==0,]
VS1 <- mtcars[mtcars$vs==1,]
ggplot() +
geom_bar(data = VS0, stat="identity", position = position_dodge(),
aes(x = cyl, y = mpg, fill = gear)) +
geom_point(data = VS1, shape = 24,
position = position_dodge(width=1),
aes(x = cyl, y = mpg, group = gear), fill = "blue")
Option 2: Facetting
ggplot(data = mtcars, group=vs) +
geom_bar(stat="identity", position = position_dodge(),
aes(x = cyl, y = mpg, fill = gear)) +
facet_grid(~vs, labeller=label_both)
For your data, maybe this would work:
DATA <- MATH[MATH$departamento %in% c("CUNDINAMARCA","COLOMBIA"),]
ggplot(data = DATA, group=departamento) +
geom_bar(stat="identity", position = position_dodge(),
aes(x = año, y = desempeño, fill = nivel)) +
facet_grid(~departamento, labeller=label_both)
Goal is to achieve ordered categories on y axis.
y1 -> y2 -> y3.
Here's the example:
require(data.table)
require(ggplot2)
dt <- data.table(var = rep("x1", 3),
categ = paste0("y", c(1,2,3)),
value = c(-2,0.5,-1))
ggplot(dt, aes(x = categ, y = value)) +
geom_bar(stat = "identity") +
coord_flip() +
theme_bw()
It seems to be reversed. Here's the one way to achieve desired ordering in ggplot2:
dt$categ <- factor(dt$categ, levels = rev(levels(factor(dt$categ))))
ggplot(dt, aes(x = categ, y = value)) +
geom_bar(stat = "identity") +
coord_flip() +
theme_bw()
Great, now ordering seems to be right. But with some modifications:
ggplot(dt, aes(x = categ, y = value)) +
geom_bar(data = dt[value < 0], stat = "identity", fill = "darkred") +
geom_bar(data = dt[value >= 0], stat = "identity", fill = "darkblue") +
coord_flip() +
theme_bw()
For some reason factor ordering is ignored here. Any clues why?
Solution could be:
# dt is original data without factors
ggplot(dt, aes(categ, value, fill = value >= 0)) +
geom_bar(stat = "identity") +
scale_fill_manual(values = c("darkred", "darkblue")) +
# since we want y1 on top and y3 on bottom we have to apply rev
scale_x_discrete(limits = rev(dt$categ)) +
coord_flip() +
theme_bw()
Trick is to pass dt$categ as limits argument to scale_x_discrete(). In your first plot order is not reversed, this is how it should be as ggplot2 starts putting values from the origin of the axis (0).
I also removed two geom_bar lines that were used in a not-ggplot way.
There was a warning when entering values in the boxplot using geom_text.
As a result of studying, it is judged that there is no 'fill' option in aes of geom_text.
I want to know what I should do to get rid of the warning message.
means <- aggregate(d13C~Species, data=scat, meam)
means$d13C <- round(means$d13C,2)
ggplot(data=scat,
mapping=aes(x=scat$Species, y=scat$d13C, fill=scat$Species)) +
geom_boxplot() +
stat_summary(fun.y=mean, colour='darkred', geom="point",
shape=3, size=3, show.legend=F) +
geom_text(data=means,
aes(x=means$Species, y = d13C+1, label=d13C, fill=Species))
Try the following
means <- aggregate(d13C ~ Species, data = scat, mean) # there was a typo here
means$d13C <- round(means$d13C, 2)
ggplot(data = scat, aes(x = Species, y = d13C)) +
geom_boxplot(aes(fill = Species)) +
stat_summary(
fun.y = mean,
colour = 'darkred',
geom = "point",
shape = 3,
size = 3,
show.legend = F
) +
geom_text(data = means, aes(x = Species, y = d13C + 1, label = d13C))
If not working properly, please share a minimal reproducible dataset.
A general advise: Don't write ggplot(data = scat, aes(x = scat$Species, y = scat$d13C)) + ... but use the bare column names in aes.
I want to plot the distribution of a variable by Class and add vertical lines denoting the means of the subsets defined by each Class and having them colored by Class. While I succeed to color the distributions by Class, the vertical lines appear gray. For a reproducible example see below:
library(data.table)
library(ggplot2)
library(ggthemes)
data(mtcars)
setDT(mtcars)
mtcars[, am := factor(am, levels = c(1, 0))]
mean_data <- mtcars[, .(mu = mean(hp)), by = am]
ggplot(mtcars, aes(x = hp, fill = am , color = am)) +
geom_histogram(aes(y=..density..), position="identity",alpha = 0.4) + guides(color = FALSE) +
geom_density (alpha = 0.5)+
geom_vline(data = mean_data, xintercept = mean_data$mu, aes(color = as.factor(mean_data$am)), size = 2, alpha = 0.5) +
ggtitle("Hp by am") + scale_fill_discrete(labels=c("am" , "no am")) +
labs(fill = "Transmission") + theme_economist()
This code renders the following plot:
Your advice will be appreciated.
You need to include the xintercept mapping in your aes call, so that ggplot properly maps all the aesthetics:
ggplot(mtcars, aes(x = hp, fill = am , color = am)) +
geom_histogram(aes(y=..density..), position="identity",alpha = 0.4) + guides(color = FALSE) +
geom_density (alpha = 0.5)+
geom_vline(data = mean_data, aes(xintercept = mu, color = as.factor(am)), size = 2, alpha = 0.5) +
ggtitle("Hp by am") + scale_fill_discrete(labels=c("am" , "no am")) +
labs(fill = "Transmission") + theme_economist()
Anything you put in a geom call that's not in aes gets treated as a one-off value, and doesn't get all the mapped aesthetics applied to it.
I try to mark my graphs with the average specific of each graph :
ggplot(diamonds, aes(x = carat, fill=cut)) +
stat_density(aes(ymax = ..density.., ymin = -..density..),
geom = "ribbon", position = "identity") +
facet_grid(. ~ cut) +
xlim(0,2.5) +
geom_text(data = NULL, x = 0.6, y = 0, label = mean(carat), size=5) +
coord_flip()
For example, here I would like the graph of "Fair" is displayed average of "Fair", that of "Good" is displayed average of "Good", etc.
Also, but this is an extra, I would like to be positioned with respect to x if the average is 1.0, while the average is displayed at x = 1.0
There are a number of ways to get the labels (and the positions for the labels). Here, the dplyr package is used to summarise the diamonds data frame; that is, to obtain the required means. Also note that the labels are formatted - two decimal places. In the code below, the diamonds2 data frame contains the means and the labels, and is used in the call to geom_text.
library(ggplot2)
library(dplyr)
diamonds2 = transform(summarise(group_by(diamonds, cut), label = mean(carat)),
Label = sprintf("%.02f", label))
ggplot(diamonds, aes(x = carat, fill=cut)) +
stat_density(aes(ymax = ..density.., ymin = -..density..),
geom = "ribbon", position = "identity") +
facet_grid(. ~ cut) +
xlim(0, 2.5) +
geom_text(data = diamonds2, aes(label = Label, x = label, y = 0), size=5) +
coord_flip()