Adding labels to ends of bars in ggplot geom_bar - r

Here's a bar chart:
ggplot(mtcars) +
geom_bar(aes(x = reorder(factor(cyl), mpg), y = mpg), stat="identity") +
coord_flip()
Should produce this:
I would like to add labels on the end showing the total value of mpg in each bar. For example, 4cyl looks to be around about 290 just from eyeballing. I want to add a label showing the exact number to the bars.
I'd like to experiment and see how they look, so for completeness:
Inside at the top of the bars
Outside the bars along the top
Bonus is I'm able to control whether the labels display vertically or horizontally.
I found this SO post but have struggled to replicate the chosen answer. Here's my attempt:
ggplot(mtcars) +
geom_bar(aes(x = reorder(factor(cyl), mpg), y = mpg), stat="identity") +
coord_flip() +
geom_text(aes(label = mpg))
Which gives an error:
Error: geom_text requires the following missing aesthetics: x, y
How can I add labels to the ends of the bars?

This would do what you need through generating a new data.frame for label plotting. You can customize the location of texts by adjusting nudge_y and angle.
library(dplyr)
tmp <- mtcars %>% group_by(cyl) %>% summarise(tot_mpg = sum(mpg))
tmp$cyl <- factor(tmp$cyl)
ggplot(mtcars) +
geom_bar(aes(x = reorder(factor(cyl), mpg), y = mpg), stat="identity") +
coord_flip() + geom_text(data = tmp, nudge_y = 10, angle = 270,
aes(x = cyl, y = tot_mpg, label = tot_mpg))

Related

How to make all values below a threshold have single color with scale continuous?

I would like to map a variable to a continuous color scale, but if the value is a below a certain threshold, it should have a specific color. In this example, I would like to make all car models with an mpg < 20 filled with gray, and everything above with the continuous color scale:
library(ggplot2)
dat <- head(mtcars)
dat$model <- head(colnames(mtcars))
dat$is_low <- ifelse(dat$mpg < 20, TRUE, FALSE)
ggplot(dat, aes(x = model, y = mpg, fill = mpg)) +
geom_col()
Is that even possible? The closest I have seen is this solution but it maps a second variably to scale_color and not to scale_fill_continuous
Not the most elegant, but you could add a layer that's filtered to just the ones you want gray:
ggplot(dat, aes(x = model, y = mpg, fill = mpg)) +
geom_col() +
geom_col(data = dat[dat$is_low,], fill = "gray70")
Add a second layer of geom_col() where you either color each bar grey or skip if it doesn't meet your criteria. You may also want to change the limits of your coloring scale for the first layer.
ggplot(dat, aes(x = model, y = mpg, fill = mpg)) +
geom_col() + geom_col(fill=ifelse(dat$mpg < 20, 'gray', NA))

ggplot- misiing values in scale x

I made that plot-
enter image description here
and that the code:
**plot <- ggplot(df, aes(mounth, value, fill=year))
plot <- plot + geom_bar(stat = "identity", position = 'dodge')+ facet_grid(. ~ variable)+ geom_text(aes(label = value),size=1.8,vjust = -0.5, position = position_dodge(0.9))+
facet_grid(. ~ variable) + ggtitle("חסות הנוער: כמות השמות לפי דיווח \n שנת 2019 VS שנת 2020")
plot**
but the first month(3) and the last month(9) disappeared from the X axis and I can not get them to appear.
Also does anyone know if there is a possibility that the plots will appear in 2 lines and not in one?
Thank you
Try this on your data. The issue is that you are providing a numeric variable to the x-axis. Instead you can use factor() so that each number can appear in the axis. Here the code (And please next time include your data of a sample of it):
#Code
plot <- ggplot(df, aes(factor(mounth), value, fill=year))
plot <- plot + geom_bar(stat = "identity", position = 'dodge')+
facet_grid(. ~ variable)+
geom_text(aes(label = value),size=1.8,vjust = -0.5, position = position_dodge(0.9))+
facet_grid(. ~ variable) +
ggtitle("חסות הנוער: כמות השמות לפי דיווח \n שנת 2019 VS שנת 2020")

Box plot with multiple groups + Dots + Counts

I have a boxplot with multiple groups in R.
When i add the dots within the boxplots, they are not in the center.
Since each week has a different number of boxplots, the dots are not centered within the box.
The problem is in the geom_point part.
I uploaded my data of df.m in a text file and a figure of what i get.
I am using ggplot, and here is my code:
setwd("/home/usuario")
dput("df.m")
df.m = read.table("df.m.txt")
df.m$variable <- as.factor(df.m$variable)
give.n = function(elita){
return(c(y = median(elita)*-0.1, label = length(elita)))
}
p = ggplot(data = df.m, aes(x=variable, y=value))
p = p + geom_boxplot(aes(fill = Label))
p = p + geom_point(aes(fill = Label), shape = 21,
position = position_jitterdodge(jitter.width = 0))
p = p + stat_summary(fun.data = give.n, geom = "text", fun.y = median)
p
Here is my data in a text file:
https://drive.google.com/file/d/1kpMx7Ao01bAol5eUC6BZUiulLBKV_rtH/view?usp=sharing
Only in variable 12 is in the center, because there are 3 groups (the maximum of possibilities!
I would also like to show the counting of observations. If I use the code shown, I can only get the number of observations for all the groups. I would like to add the counting for EACH GROUP.
Thank you in advance
enter image description here
Here's a solution using boxplot and dotplot and an example dataset:
library(tidyverse)
# example data
dt <- data.frame(week = c(1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2),
value = c(6.40,6.75,6.11,6.33,5.50,5.40,5.83,4.57,5.80,
6.00,6.11,6.40,7.00,3,5.44,6.00,5,6.00),
donor_type = c("A","A","A","A","CB","CB","CB","CB","CB",
"CB","CB","CB","CB","CB","A","A","A","A"))
# create the plot
ggplot(dt, aes(x = factor(week), y = value, fill = donor_type)) +
geom_boxplot() +
geom_dotplot(binaxis='y', stackdir='center', position = position_dodge(0.75))
You should be able to adjust my code to your real dataset easily.
Edited answer with OP's dataset:
Using some generated data and geom_point():
library(tidyverse)
df.m <- df.m %>%
mutate(variable = as.factor(variable)) %>%
filter(!is.na(value))
ggplot(df.m, aes(x = variable, y = value, fill = Label)) +
geom_boxplot() +
geom_point(shape = 21, position = position_jitterdodge(jitter.width = 0)) +
scale_x_discrete("variable", drop = FALSE)

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)

ggplot2: Create an empty space on the x-axis

On the below plot, I'd like to create an empty space on the x-axis at position 3. In other word, I'd like that the dots for wt>=3 and the axis scale when wt>=3 are shifted to the right side by some arbitrary chosen value. Does it make sense?
ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point()
I could simply modify the my data and add 0.5 to each value of mpg where wt>=3 but it doesn't solve the issue with the x-axis.
I might rephrase my question saying that on the below graph I'd like that the vertical line does not overlap the data and therefore all the data (and also the x-axis) should be shifted to the left by the thickness of the vertical line.
ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point() + geom_vline(xintercept=3, size=30)
I was thinking about facet_wrap or viewport. Maybe something like adding a constant to each value of mpg where wt>=3 and then, manually set the values for the x-axis.
Not entirely sure what you are looking for, and I get confused by watching the weird axis on my own plot... Something like this?
mtcars$wt2 <- with(mtcars, ifelse(wt > 3, wt+1, wt))
ggplot(mtcars, aes(x = wt2, y = mpg)) +
geom_point() +
annotate("rect", xmin = 3, xmax = 4, ymin = 0, ymax = 35, alpha = 0.2) +
scale_x_continuous(breaks = round(mtcars$wt2), label = round(mtcars$wt))
Similar to # Frank, and tested...
x <- mtcars
x$group <- ""
x[x$wt<3,]$group <- "1.LIGHT"
x[x$wt>=3,]$group <- "2.HEAVY"
library(ggplot2)
library(grid) #for unit(...)
ggplot(x, aes(x=wt,y=mpg)) +
geom_point() +
facet_grid(~group,scales="free",space="free") +
theme(panel.margin = unit(2, "lines"))
Produces this:
what about something like this?
mtcars <- transform(mtcars, split = ifelse(wt >= 3, "b", "a" ))
ggplot(mtcars, aes(x = wt, y = mpg)) +
geom_point() +
facet_wrap(~split, scales = "free_x")

Resources