library(dplyr)
#Code
mpg %>%
mutate(Color=ifelse(class=='2seater','2seater','Other')) %>%
ggplot(aes(displ, hwy, colour = Color)) +
geom_point()
In the above code if i would like to separately label 2 wheeler on top of the blue dots for 2 wheeler instead of a separate column for legends, what would be the modification for my code pls?
Not sure if I understand you correctly, but does this answer your question?
library(ggplot2)
library(dplyr)
#install.packages("ggrepel")
library(ggrepel)
#Code
mpg %>%
mutate(Color=ifelse(class == '2seater','2seater','Other')) %>%
ggplot(aes(displ, hwy, colour = Color)) +
geom_point() +
geom_text_repel(aes(label = ifelse(Color == '2seater', '2seater', "")),
ylim = 35, force_pull = 0, show.legend = FALSE)
Or perhaps this?
library(ggplot2)
library(dplyr)
#install.packages("ggrepel")
library(ggrepel)
#Code
mpg %>%
mutate(Color=ifelse(class == '2seater','2seater','Other')) %>%
ggplot(aes(displ, hwy, colour = Color)) +
geom_point() +
geom_text_repel(aes(label = ifelse(Color == '2seater', '2seater', "")),
force_pull = 0, show.legend = FALSE) +
theme(legend.position = "none")
Or some combination of the two?
Related
library(ggplot2)
library(dplyr)
#install.packages("ggrepel")
library(ggrepel)
#Code
mpg %>%
mutate(Color=ifelse(class == '2seater','2seater','Other')) %>%
ggplot(aes(displ, hwy, colour = Color)) +
geom_point() +
geom_text_repel(aes(label = ifelse(Color == '2seater', '2seater', "")),
force_pull = 0, show.legend = FALSE) +
theme(legend.position = "none")
in the above code if I want to add another label for 'compact' how would I change the code please, so i would like 2 labels- one for compact and 2seater
You can do with case_when where you have used if else. [Although you could use an ifelse inside another ifelse. But I find case_when cleaner.]
But have a look. Aren't there too many labels? Why not just leave it color coded?
library(ggplot2)
library(dplyr)
library(ggrepel)
#Code
ggplot2::mpg %>%
mutate(Color = case_when(
class == "2seater" ~ "2seater",
class == "compact" ~ "compact",
TRUE ~ "other"
)) %>%
ggplot(aes(displ, hwy, colour = Color)) +
geom_point() +
geom_text_repel(aes(
label =
case_when(
class == "2seater" ~ "2seater",
class == "compact" ~ "compact"
)
),
force_pull = 0, show.legend = FALSE
) +
scale_color_manual(values = c("red", "blue", "gray")) +
theme(legend.position = "none")
As an alternative to the case_when() method proposed by MarBlo, you can also subset the data while specifying the layer. Upside is that is shorter to write, downside is that the labels don't repel the unlabelled points. As mentioned by MarBlo, ggrepel protests that there might be too many labels.
library(ggplot2)
library(dplyr)
library(ggrepel)
mpg %>%
mutate(Color=ifelse(class == '2seater','2seater','Other')) %>%
ggplot(aes(displ, hwy, colour = Color)) +
geom_point() +
geom_text_repel(aes(label = class),
data = ~ subset(., class %in% c("2seater", "compact")),
force_pull = 0, show.legend = FALSE) +
theme(legend.position = "none")
#> Warning: ggrepel: 31 unlabeled data points (too many overlaps). Consider
#> increasing max.overlaps
Created on 2021-01-10 by the reprex package (v0.3.0)
data(mtcars)
library(ggplot2)
ggplot(mtcars, aes(x = reorder(row.names(mtcars), mpg), y = mpg, fill = factor(cyl))) +
geom_bar(stat = "identity")
This will ggplot the bars with solid fills but what if I wish to use the same fill colors as outlines for some measures but solid fills for others. For example if 'am' equals to 1 it is solid fill but if 'am' equals to 0 than it is just an outline fill like this sample:
One option to remove the fill based on a logical condition is to change those values to NA.
library(tidyverse)
d <- head(mtcars) %>%
rownames_to_column() %>%
# make a new variable for fill
# note: don't use ifelse on a factor!
mutate(cyl_fill = ifelse(am == 0, NA, cyl),
# now make them factors
# (you can do this inside ggplot, but that is messy)
cyl = factor(cyl),
cyl_fill = factor(cyl_fill, levels = levels(cyl)))
# plot
p <- ggplot(d) +
aes(x = rowname,
y = mpg,
color = cyl,
fill = cyl_fill
) +
geom_bar(stat = "identity") +
theme(axis.text.x = element_text(angle = 90))
# change the fill color of NA values
p + scale_fill_discrete(drop=FALSE, na.value="white")
If you want NA fill values to be empty and omitted from the legend:
# omit the fill color of NA values
# note: drop=FALSE is still needed to keep the fill and (outline) color values the same
p + scale_fill_discrete(drop=FALSE, na.translate = F)
You can change the color of the outline in the same way (e.g. cyl_color = ifelse(am != 0, NA, Cyl)), but if you want to specify a color like white or black, it will (should) appear in the legend. You can try to hack your way around these wise defaults by plotting non-aesthetic layers behind your main layers, but it usually gets ugly:
head(mtcars) %>%
rownames_to_column() %>%
mutate(cyl_fill = ifelse(am == 0, NA, cyl),
cyl_color = ifelse(am != 0, NA, cyl),
cyl = factor(cyl),
cyl_fill = factor(cyl_fill, levels = levels(cyl)),
cyl_color = factor(cyl_color, levels = levels(cyl))) %>%
ggplot() +
aes(x = rowname,
y = mpg,
color = cyl_color,
fill = cyl_fill
) +
geom_bar(stat = "identity", color = "black") + # NON-AES LAYER FIRST
geom_bar(stat = "identity") + # Covers up the black except where omitted
theme(axis.text.x = element_text(angle = 90))+
scale_fill_discrete(drop=FALSE, na.translate = F) +
scale_color_discrete(drop=FALSE, na.translate = F)
You could assign the desired colors to each level of the fill and color variables. For example:
library(tidyverse)
mtcars %>%
rownames_to_column() %>%
arrange(mpg) %>%
mutate(rowname=factor(rowname, levels=rowname)) %>%
ggplot(aes(x = rowname, y = mpg, fill = factor(am), colour=factor(cyl))) +
geom_col(size=1) +
scale_fill_manual(values=c("0"="white", "1"="red")) +
scale_color_manual(values=c("4"="blue", "6"="orange", "8"="white")) +
theme_classic() +
theme(axis.text.x=element_text(angle=-90, vjust=0.5, hjust=0))
May be, we can do
library(dplyr)
library(ggplot2)
mtcars %>%
mutate(new = case_when(am == 1 ~ factor(cyl)),
new1 = case_when(am !=1 ~ factor(cyl))) %>%
ggplot(aes(x = reorder(row.names(mtcars), mpg), y = mpg,
fill = new, color = new1)) +
geom_bar(stat = 'identity') +
scale_fill_discrete(na.value= NA) + # similar to Devin Judge-Lord post
theme_classic() +
theme(axis.text.x=element_text(angle=-90, vjust=0.5, hjust=0))
I am trying to create a chart, with a 'ribbon' behind the chart highlighting a specific client. However, if I try to add the ribbon, the sorting I've put together disappears and it reverts. Here's an example:
Sorted correctly, but no ribbon:
library(tibble)
library(dplyr)
library(stringr)
library(ggplot2)
mtcars %>%
ungroup() %>%
rownames_to_column("Car") %>%
mutate(Brand = word(Car, 1,1, sep = " ")) %>%
mutate(Brand = ifelse(Brand %in% c('Fiat','Toyota','Hornet', 'Merc'), Brand, 'zOther')) %>%
mutate(focus = ifelse(Brand == 'Toyota', Brand, NA_character_)) %>%
mutate(Brand=reorder(Brand, mpg, mean)) %>%
ggplot(aes(x = Brand, y = mpg)) +
geom_point() +
coord_flip() +
theme_classic() +
NULL
Ribbon added, but losing sort:
library(tibble)
library(dplyr)
library(stringr)
library(ggplot2)
mtcars %>%
ungroup() %>%
rownames_to_column("Car") %>%
mutate(Brand = word(Car, 1,1, sep = " ")) %>%
mutate(Brand = ifelse(Brand %in% c('Fiat','Toyota','Hornet', 'Merc'), Brand, 'zOther')) %>%
mutate(focus = ifelse(Brand == 'Toyota', Brand, NA_character_)) %>%
mutate(Brand=reorder(Brand, mpg, mean)) %>%
ggplot(aes(x = Brand, y = mpg)) +
geom_point() +
geom_linerange(aes(x=focus,ymin=-Inf,ymax=Inf), colour="grey", size=23, alpha=0.3) +
coord_flip() +
theme_classic() +
NULL
I have successfully done this in the past, but nothing seems to be co-operating today. What am I doing wrong?
geom_linerange() is not the right function for your purpose.
A better option in my opinion is using annotate(geom = "rect", ...)
ggplot(data, aes(x = Brand, y = mpg)) +
scale_x_discrete() +
annotate("rect", xmin = 3.5, xmax = 4.5, ymin = -Inf, ymax = Inf, fill = "lightgrey", alpha=0.6) +
geom_point() +
coord_flip() +
theme_classic() +
NULL
EDIT: To pass the ribbon in as a variable do:
mtcars %>%
ungroup() %>%
rownames_to_column("Car") %>%
mutate(Brand = word(Car, 1,1, sep = " ")) %>%
mutate(Brand = ifelse(Brand %in% c('Fiat','Toyota','Hornet', 'Merc'), Brand, 'zOther')) %>%
mutate(focus = ifelse(Brand == 'Toyota', 0.6, 0)) %>%
mutate(Brand=reorder(Brand, mpg, mean)) %>%
ggplot(aes(x = Brand, y = mpg)) +
geom_linerange(aes(x=Brand,ymin=-Inf,ymax=Inf, alpha=I(focus)), colour="grey", size=23) +
geom_point() +
coord_flip() +
theme_classic() +
NULL
Your focus-variable now contains the alpha value. 0.6 for Toyota and 0 for everyone else. Inside the aes() statement of geom_linerange() we assign focus to the alpha= aesthetic "as is", meaning taking our values 0.6and 0.
In the plot below I'd like to move the label "V-Engine" into the plot margin. Adjusting the nudge_x argument is moving the "S-Engine" label but not the "V-Engine" label.
library(ggplot2)
library(ggrepel)
library(dplyr)
ds <-
mtcars %>%
mutate(vs = factor(vs, labels = c("V-Engine", "S-Engine"))) %>%
# Create labels for the rightmost data points
group_by(vs) %>%
mutate(
label =
case_when(
wt == max(wt) ~ as.character(vs),
TRUE ~ NA_character_
)
) %>%
ungroup()
ds %>%
ggplot(aes(x = wt, y = mpg, color = vs)) +
geom_smooth(se=FALSE) +
geom_label_repel(aes(label = label), nudge_x = 1, na.rm = TRUE) +
guides(color = FALSE) +
theme_minimal() +
theme(plot.margin = unit(c(1,3,1,1), "cm"))
You can set xlim() inside geom_label_repel
library(dplyr)
library(ggplot2)
library(ggrepel)
ds %>%
ggplot(aes(x = wt, y = mpg, color = vs)) +
geom_smooth(se=FALSE) +
geom_label_repel(aes(label = label),
nudge_x = 1,
# direction = 'x',
xlim = c(0, 6.5),
na.rm = TRUE) +
guides(color = FALSE) +
theme_minimal() +
theme(plot.margin = unit(c(1,3,1,1), "cm")) +
coord_cartesian(clip = 'off')
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'
Created on 2018-11-16 by the reprex package (v0.2.1.9000)
How does one plot "filled" bars with counts labels using ggplot2?
I'm able to do this for "stacked" bars. But I'm very confused otherwise.
Here is a reproducible example using dplyr and the mpg dataset
library(ggplot)
library(dplyr)
mpg_summ <- mpg %>%
group_by(class, drv) %>%
summarise(freq = n()) %>%
ungroup() %>%
mutate(total = sum(freq),
prop = freq/total)
g <- ggplot(mpg_summ, aes(x = class, y = prop, group = drv))
g + geom_col(aes(fill = drv)) +
geom_text(aes(label = freq), position = position_stack(vjust = .5))
But if I try to plot counts for filled bars it does not work
g <- ggplot(mpg_summ, aes(x=class, fill=drv))
g + stat_count(aes(y = (..count..)/sum(..count..)), geom="bar", position="fill") +
scale_y_continuous(labels = percent_format())
Further, if I try:
g <- ggplot(mpg_summ, aes(x=class, fill=drv))
g + geom_bar(aes(y = freq), position="fill") +
geom_text(aes(label = freq), position = "fill") +
scale_y_continuous(labels = percent_format())
I get:
Error: stat_count() must not be used with a y aesthetic.
I missed the fill portion from the last question. This should get you there:
library(ggplot2)
library(dplyr)
mpg_summ <- mpg %>%
group_by(class, drv) %>%
summarise(freq = n()) %>%
ungroup() %>%
mutate(total = sum(freq),
prop = freq/total)
g <- ggplot(mpg_summ, aes(x = class, y = prop, group = drv))
g + geom_col(aes(fill = drv), position = 'fill') +
geom_text(aes(label = freq), position = position_fill(vjust = .5))