Ggplot2 0.9.0 Automatically Dropping Unused Factor Levels from Plot Legend

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)

Prevent ggplotly to drop unused factor levels from legend

As far as I know there is no direct way of doing it but you could add a "dummy" line for each missing group value, e.g.

for (diff in setdiff(levels(dd$group), unique(dd$group))) {
dummy_name = paste0('dummy_', diff)
dd[dummy_name,] <- dd[1,]
for (n in names(dd[1,])) {
dd[dummy_name,][n] = NaN
}
dd[dummy_name,]$group <- diff
}

which will give the following dataframe

          x xend         y     yend group
7 1 1 -2.592981 2.531884 C
8 2 2 -3.052151 2.570183 A
9 3 3 -3.255346 2.663808 C
10 4 4 -3.456388 2.905152 A
dummy_B NaN NaN NaN NaN B

and the following plot

Sample Image



dd = structure(list(x = c(1, 2, 3, 4), 
xend = c(1, 2, 3, 4),
y = c(-2.59298110869713, -3.05215109954588, -3.25534630590118, -3.45638777944259),
yend = c(2.53188374522142, 2.57018254452851, 2.66380767012015, 2.90515183040407),
group = structure(c(3L, 1L, 3L, 1L),
.Label = c("A", "B", "C"),
class = "factor")),
.Names = c("x", "xend", "y", "yend", "group"),
class = "data.frame",
row.names = 7:10)
for (diff in setdiff(levels(dd$group), unique(dd$group))) {
dummy_name = paste0('dummy_', diff)
dd[dummy_name,] <- dd[1,]
for (n in names(dd[1,])) {
dd[dummy_name,][n] = NaN
}
dd[dummy_name,]$group <- diff
}

gg <- ggplot(dd, aes(x, y, color=group)) +
scale_colour_discrete(drop = FALSE) +
geom_segment(aes(xend=xend, yend=yend))

gg
ggplotly(ggplot(dd, aes(x, y, color=group)) +
scale_colour_discrete(drop = FALSE) +
geom_segment(aes(xend=xend, yend=yend)))

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.

Keeping unused factor in legend in ggplot2 - drop=FALSE not effective

Of course the "levels" are dropped. You don't have a factor until you pass it to ggplot that coerces it to one... Instead, explicitly make birds a factor before you call the function.

all.birds$birds <- factor(all.birds$birds)

Then run your loop. If I've misunderstood, please clarify.

ggplot: how to remove unused factor levels from a facet?

Setting scales = free in facet grid will do the trick:

facet_grid( ~ fac, scales = "free")

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

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:
Sample Image

R: Is there a way to add unused data levels in a ggplot legend?

Here's a working example with mtcars, taken from the ggplot2 documentation here. Namely, you can use scale_color_manual with the limits argument instead.

Edit after comment below: the limits argument is what is important, you can pass it to both scale_color_manual or scale_fill_manual.

cols <- c("8" = "red","4" = "blue","6" = "darkgreen", "10" = "orange")
plot <- ggplot(mtcars, aes(x = mpg, y = wt, colour = factor(cyl))) + geom_point()
plot + scale_color_manual(values = cols,
limits = c("4", "6", "8", "10"),
labels = c("this", "is", "my", "test"))

Sample Image

That should be enough for you to adapt it to your problem. It's hard for me be sure this will work without having your actual data set, but here is a solution that should work:

cols= c("0"="#F0F0F0","1"="green","2"="red","3"="blue","4"="purple")

ggplot(spat.dataframe, aes(long,lat,group=group)) + # the data
geom_polygon(aes(fill=as.factor(qt))) + # make polygons
scale_fill_manual(limits = c("0", "1", "2", "3", "4")
values = cols,
labels = c(paste0("white (",length(spat.dataframe[spat.dataframe$qt==0,]),")"),
paste0("green (",length(spat.dataframe[spat.dataframe$qt==1,]),")"),
paste0("red (",length(spat.dataframe[spat.dataframe$qt==2,]),")"),
paste0("blue (",length(spat.dataframe[spat.dataframe$qt==3,]),")"),
paste0("pink (",length(spat.dataframe[spat.dataframe$qt==4,]),")")),
drop=F,
name=NULL) +
theme(line = element_blank(), # remove the background, tickmarks, etc
axis.text = element_blank(),
axis.title = element_blank(),
panel.background = element_blank()) +
ggtitle(title) +
geom_path( colour = "#6b6b6b", size = .5 ) +
coord_equal()


Related Topics



Leave a reply



Submit