Plot proportion in bar chart grouped by another variable - r

I am currently reading R for Data Science and trying to create some graphs. I understand that to get proportion in bar chart, you need to use group = 1. For example, the code below works:
library(ggplot2)
ggplot(data = diamonds) + geom_bar(mapping = aes(x = cut, fill = color))
But I don't get the same plot for proportions.
ggplot(data = diamonds) + geom_bar(mapping = aes(x = cut, fill = color, y = ..prop.., group = 1))
I do get proportion but not by color.

Here's one way to do it using ..count..
require(ggplot2)
ggplot(diamonds,aes(cut,..count../sum(..count..),fill=color))+
geom_bar()+
scale_y_continuous(labels=scales::percent)

Related

Unintended line across X axis of density plot (r)

I am trying to identify why I have a purple line appearing along the x axis that is the same color as "Prypchan, Lida" from my legend. I took a look at the data and do not see any issues there.
ggplot(LosDoc_Ex, aes(x = LOS)) +
geom_density(aes(colour = AttMD)) +
theme(legend.position = "bottom") +
xlab("Length of Stay") +
ylab("Distribution") +
labs(title = "LOS Analysis * ",
caption = "*exluding Residential and WSH",
color = "Attending MD: ")
Usually I'd wait for a reproducible example, but in this case, I'd say the underlying explanation is really quite straightforward:
geom_density() creates a polygon, not a line.
Using a sample dataset from ggplot2's own package, we can observe the same straight line below the density plots, covering the x-axis & y-axis. The colour of the line simply depends on which plot is on top of the rest:
p <- ggplot(diamonds, aes(carat, colour = cut)) +
geom_density()
Workaround 1: You can manually calculate the density values yourself for each colour group in a new data frame, & plot the results using geom_line() instead of geom_density():
library(dplyr)
library(tidyr)
library(purrr)
diamonds2 <- diamonds %>%
nest(-cut) %>%
mutate(density = map(data, ~density(.x$carat))) %>%
mutate(density.x = map(density, ~.x[["x"]]),
density.y = map(density, ~.x[["y"]])) %>%
select(cut, density.x, density.y) %>%
unnest()
ggplot(diamonds2, aes(x = density.x, y = density.y, colour = cut)) +
geom_line()
Workaround 2: Or you can take the data generated by the original plot, & plot that using geom_line(). The colours would need to be remapped to the legend values though:
lp <- layer_data(p)
if(is.factor(diamonds$cut)) {
col.lev = levels(diamonds$cut)
} else {
col.lev = sort(unique(diamonds$cut))
}
lp$cut <- factor(lp$group, labels = col.lev)
ggplot(lp, aes(x = x, y = ymax, colour = cut)) +
geom_line()
There are two simple workarounds. First, if you only want lines and no filled areas, you can simply use geom_line() with the density stat:
library(ggplot2)
ggplot(diamonds, aes(x = carat, y = stat(density), colour = cut)) +
geom_line(stat = "density")
Note that for this to work, we need to set the y aesthetic to stat(density).
Second, if you want the area under the lines to be filled, you can use geom_density_line() from the ggridges package. It works exactly like geom_density() but draws a line (with filled area underneath) rather than a polygon.
library(ggridges)
ggplot(diamonds, aes(x = carat, colour = cut, fill = cut)) +
geom_density_line(alpha = 0.2)
Created on 2018-12-14 by the reprex package (v0.2.1)

How to create a heatmap with continuous scale using ggplot2 in R

I have got a data frame with several 1000 rows in the form of
group = c("gr1","gr1","gr1","gr1","gr1","gr1","gr1","gr1","gr1","gr1","gr2","gr2","gr2","gr2","gr2","gr2","gr2","gr2","gr2","gr2","gr3","gr3","gr3","gr3","gr3","gr3","gr3","gr3","gr3","gr3")
pos = c(1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10)
color = c(2,2,2,2,3,3,2,2,3,2,1,2,2,2,1,1,1,1,1,1,2,2,2,2,2,2,1,1,2,2)
df = data.frame(group, pos, color)
and would like to make a kind of heatmap in which one axes has a continuous scale (position). The color column is categorical. However due to the large amount of data points I want to use binning, i.e. use it as a continuous variable.
This is more or less how the plot should look like:
I can't think of a way to create such a plot using ggplot2/R. I have tried several geometries, e.g. geom_point()
ggplot(data=df, aes(x=strain, y=pos, color=color)) +
geom_point() +
scale_colour_gradientn(colors=c("yellow", "black", "orange"))
Thanks for your help in advance.
Does this help you?
library(ggplot2)
group = c("gr1","gr1","gr1","gr1","gr1","gr1","gr1","gr1","gr1","gr1","gr2","gr2","gr2","gr2","gr2","gr2","gr2","gr2","gr2","gr2","gr3","gr3","gr3","gr3","gr3","gr3","gr3","gr3","gr3","gr3")
pos = c(1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10)
color = c(2,2,2,2,3,3,2,2,3,2,1,2,2,2,1,1,1,1,1,1,2,2,2,2,2,2,1,1,2,2)
df = data.frame(group, pos, color)
ggplot(data = df, aes(x = group, y = pos)) + geom_tile(aes(fill = color))
Looks like this
Improved version with 3 color gradient if you like
library(scales)
ggplot(data = df, aes(x = group, y = pos)) + geom_tile(aes(fill = color))+ scale_fill_gradientn(colours=c("orange","black","yellow"),values=rescale(c(1, 2, 3)),guide="colorbar")

Color outliers multiple factors in boxplot

Let's say I have the following data frame:
library(ggplot2)
set.seed(101)
n=10
df<- data.frame(delta=rep(rep(c(0.1,0.2,0.3),each=3),n), metric=rep(rep(c('P','R','C'),3),n),value=rnorm(9*n, 0.0, 1.0))
My goal is to do a boxplot by multiple factors:
p<- ggplot(data = df, aes(x = factor(delta), y = value)) +
geom_boxplot(aes(fill=factor(metric)))
The output is:
So far so good, but if I do:
p+ geom_point(aes(color = factor(metric)))
I get:
I do not know what it is doing. My goal is to color the outliers as it is done here. Note that this solution changes the inside color of the boxes to white and set the border to different colors. I want to keep the same color of the boxes while having the outliers inherit those colors. I want to know how to make the outliers get the same colors from their respective boxplots.
Do you want just to change the outliers' colour ? If so, you can do it easily by drawing boxplot twice.
p <- ggplot(data = df, aes(x = factor(delta), y = value)) +
geom_boxplot(aes(colour=factor(metric))) +
geom_boxplot(aes(fill=factor(metric)), outlier.colour = NA)
# outlier.shape = 21 # if you want a boarder
[EDITED]
colss <- c(P="firebrick3",R="skyblue", C="mediumseagreen")
p + scale_colour_manual(values = colss) + # outliers colours
scale_fill_manual(values = colss) # boxes colours
# the development version (2.1.0.9001)'s geom_boxplot() has an argument outlier.fill,
# so I guess under code would return the similar output in the near future.
p2 <- ggplot(data = df, aes(x = factor(delta), y = value)) +
geom_boxplot(aes(fill=factor(metric)), outlier.shape = 21, outlier.colour = NA)
Maybe this:
ggplot(data = df, aes(x = as.factor(delta), y = value,fill=as.factor(metric))) +
geom_boxplot(outlier.size = 1)+ geom_point(pch = 21,position=position_jitterdodge(jitter.width=0))

R ggplot2 (mpg): Group boxplot by year rather than drv

I am working my way through R4DS, and am trying to tweak my solution for 3.8.1 exercise 4. I ended up with the following code:
ggplot(data = mpg, mapping = aes(x = manufacturer, y = hwy/cty, colour = year)) +
geom_boxplot() + coord_flip()
This does not work as intended. But when I replace colour = year with colour = drv, I get a nice grouped boxplot. Why can’t this be done with year?
RStudio 0.99.902; ggplot2 v. 2.1.0.
Seems to work when you write it into geom_boxplot.
ggplot(data = mpg, mapping = aes(x = manufacturer, y = hwy/cty)) +
geom_boxplot(aes(colour=factor(year))) + coord_flip()

ggplot bar_plot with 3 levels [duplicate]

I'm hoping to use ggplot2 to generate a set of stacked bars in pairs, much like this:
With the following example data:
df <- expand.grid(name = c("oak","birch","cedar"),
sample = c("one","two"),
type = c("sapling","adult","dead"))
df$count <- sample(5:200, size = nrow(df), replace = T)
I would want the x-axis to represent the name of the tree, with two bars per tree species: one bar for sample one and one bar for sample two. Then the colors of each bar should be determined by type.
The following code generates the stacked bar with colors by type:
ggplot(df, aes(x = name, y = count, fill = type)) + geom_bar(stat = "identity")
And the following code generates the dodged bars by sample:
ggplot(df, aes(x = name, y = count, group = sample)) + geom_bar(stat = "identity", position = "dodge")
But I can't get it to dodge one of the groupings (sample) and stack the other grouping (type):
ggplot(df, aes(x = name, y = count, fill = type, group = sample)) + geom_bar(stat = "identity", position = "dodge")
One workaround would be to put interaction of sample and name on x axis and then adjust the labels for the x axis. Problem is that bars are not put close to each other.
ggplot(df, aes(x = as.numeric(interaction(sample,name)), y = count, fill = type)) +
geom_bar(stat = "identity",color="white") +
scale_x_continuous(breaks=c(1.5,3.5,5.5),labels=c("oak","birch","cedar"))
Another solution is to use facets for name and sample as x values.
ggplot(df,aes(x=sample,y=count,fill=type))+
geom_bar(stat = "identity",color="white")+
facet_wrap(~name,nrow=1)

Resources