ggplot2 keep unused levels barplot
You need to set drop=FALSE on both scales (fill and x) like this:
library(ggplot2)
df <- data.frame(type=c("A", "A", "A", "B", "B"), group=rep("group1", 5))
df1 <- data.frame(type=c("A", "A", "A", "B", "B", "A", "A", "C", "B", "B"), group=c(rep("group1", 5),rep("group2", 5)))
df$type <- factor(df$type, levels=c("A","B", "C"))
df1$type <- factor(df1$type, levels=c("A","B", "C"))
plt <- ggplot(df, aes(x=type, fill=type)) +
geom_bar(position='dodge') +
scale_fill_discrete(drop=FALSE) +
scale_x_discrete(drop=FALSE)
plt1 <- ggplot(df1, aes(x=type, fill=type)) +
geom_bar(position='dodge') +
scale_fill_discrete(drop=FALSE) +
scale_x_discrete(drop=FALSE)
Edit:
I'm pretty sure this works. Forgot to change x to type instead of group and the position='dodge'! Just paste and test. The stat_bin deals with bins with zero counts. Check the docs.
How to make ggplot2 keep unused levels on data subset
The issue here is that a count of zero is not generated for sps = TAST, forage = CF. You can create that count using tidyr::complete
. I've also added some dplyr
functions to make the code cleaner. Assuming that your data frame is named df1
(as opposed to data
, which is a base function name so not a good choice):
UPDATED: with stringsAsFactors = FALSE
to address issues in comments.
library(dplyr)
library(tidyr)
library(ggplot2)
df1 <- read.table("data.txt", header = TRUE, stringsAsFactors = FALSE)
df1 %>%
filter(sps != "MICRO") %>%
group_by(sps) %>%
count(forage) %>%
ungroup %>%
complete(sps, forage, fill = list(n = 0)) %>%
ggplot(aes(sps, n)) + geom_col(aes(fill = forage), position = "dodge") +
scale_x_discrete(labels=c("Marmot","American Mink", "Weasel Spp.", "Red squirrel", "Chipmunk")) +
theme_classic() +
scale_fill_manual(values=c("#000000", "#666666", "#999999","#CCCCCC"), name = "Event") +
labs(x = "Species", y = "Number of observations")
Result:
Remove unused factor levels from a ggplot bar plot
One easy options is to use na.omit()
on your data frame df
to remove those rows with NA
ggplot(na.omit(df), aes(x=name,y=var1)) + geom_bar()
Given your update, the following
ggplot(df[!is.na(df$var1), ], aes(x=name,y=var1)) + geom_bar()
works OK and only considers NA
in Var1
. Given that you are only plotting name
and Var
, apply na.omit()
to a data frame containing only those variables
ggplot(na.omit(df[, c("name", "var1")]), aes(x=name,y=var1)) + geom_bar()
ggplot2 0.9.0 automatically dropping unused factor levels from plot legend?
Yes, you want to add drop = FALSE
to your colour scale:
ggplot(subset(df,fruit == "apple"),aes(x = year,y = qty,colour = fruit)) +
geom_point() +
scale_colour_discrete(drop = FALSE)
Hide unused levels in ggplot legend
OK; the related issue 4511 gives the answer. Setting limits = force
in scale_fill_manual did it.
Drop unused levels in facet_wrap in ggplot2
Specify scales = "free_y"
figure.gg = ggplot(data = df, aes(x = group1, y = est, ymin = lwr, ymax = upr)) +
geom_point(position = position_dodge(width = 0.5)) +
geom_errorbar(position = position_dodge(width = 0.5), width = 0.1) +
coord_flip() +
# Facet wrapped with one column using group 2s
facet_wrap(~group2, ncol = 1, strip.position = "right", scales = "free_y") +
ylab("estimate")
figure.gg
Move empty factor levels while maintaining order of non-empty levels in ggplot2
This was surprisingly tricky - given that all you need to do is order your levels correctly. I couldn't find anything in forcats
that was directly appropriate, but we can write our own reordering function.
my_reorder <- function (fac, var) {
fac <- fct_reorder(fac, {{var}})
l <- levels(fac)
nonempty <- levels(factor(fac)) # I got this idea from droplevels()
empty <- setdiff(l, nonempty)
fct_relevel(fac, empty, nonempty)
fct_relevel(fac, empty, nonempty)
}
mtcars %>%
mutate(cyl = as.factor(cyl),
cyl = fct_expand(cyl, c("2", "4", "6", "8"))) %>%
group_by(cyl) %>%
summarize(meanMPG = mean(mpg)) %>%
ungroup() %>%
mutate(cyl = my_reorder(cyl, meanMPG)) %>%
ggplot(aes(x = cyl, y = meanMPG)) +
geom_col() +
scale_x_discrete(drop = FALSE, ) +
coord_flip() # shows empty level "2" on the top
ggplot2 barplot bar colour can't be changed properly
You can try these adjustments to
a) achieve the green bar colour and
b) simplify the code
- use
geom_col
rather thangeom_bar
with stat = "identity" - swap x and y values and associated scales etc to avoid using coord_flip
- remove the
limits
argument in the call toscale_fill_manual
- convert
Komp
to a factor to control order of values in ggplot.
library(ggplot2)
library(forcats)
library(dplyr)
komp_cat <- c("Smartphone", "PC/Laptop", "Tablet", "TV", "Spielkonsole", "Smart-Watch", "E-Book-Reader", "Andere")
df1<- data.frame(
Komp = rep(komp_cat, 2),
groupW = c(
rep("ja", 8),
rep("nein", 8)),
valuesW = c (100-0, 100-23.9, 100-41.3, 100-30.9, 100-51.5, 100-73.2, 100-89.8, 100-98.9 ,0, 23.9, 41.3, 30.9, 51.5, 73.2, 89.8, 98.9)
)
df1 %>%
mutate(Komp = factor(Komp, levels = komp_cat)) %>%
ggplot( aes(x = valuesW, y = fct_rev(Komp), fill = rev(groupW))) +
geom_col(position = "dodge", color = "#8DAE10", show.legend = FALSE)+
xlab("Prozent")+
ylab("")+
scale_fill_manual(values = rep("#8DAE10", 2))+
geom_text(aes (label = round(valuesW,1)),
color = "black",
hjust = -0.35,
size = 4,
position = position_dodge(width = 0.9))+
geom_text(aes(x=0, label = groupW),
color = "white",
hjust = 0,
size = 5,
position = position_dodge(width = 0.9))+
scale_x_continuous(expand = c(0.04, 0), label = scales::comma, position = "bottom")
Created on 2021-09-22 by the reprex package (v2.0.0)
Related Topics
Ggplot2 Two-Line Label With Expression
Custom Legend For Multiple Layer Ggplot
R Install.Packages Returns "Failed to Create Lock Directory"
How to Fill Geom_Polygon With Different Colors Above and Below Y = 0 (Or Any Other Value)
Change Timezone in a Posixct Object
Detect At Least One Match Between Each Data Frame Row and Values in Vector
Addressing X and Y in Aes by Variable Number
Can You Pass-By-Reference in R
Geom_Rect and Alpha - Does This Work With Hard Coded Values
Dplyr Summarise: Equivalent of ".Drop=False" to Keep Groups With Zero Length in Output
How to Send an Email With Attachment from R in Windows
R Apply() Function on Specific Dataframe Columns