I suspect I might be using group incorrectly here, but I can't seem to understand why the fill color is getting ignored in the example below.
df <- data.frame(a = factor(c(1,1,2,2,1,2,1,2)),
b = factor(c(1,2,3,4,5,6,7,2)),
c = factor(c(1,2,1,2,1,2,1,2)))
p <- ggplot(df, aes(x=b)) +
geom_bar(aes(y = ..density.., group = c, fill=a), binwidth = 1) +
facet_wrap(~ c) +
scale_y_continuous(labels = percent_format()) +
scale_color_hue()
p
Any help would be greatly appreciated.
Thanks in advance,
--JT
I think I understand what plot you're after now. I'd do something like this:
df <- data.frame(a = c(1,1,2,2,1,2,1,2),
b = c(1,2,3,4,5,6,7,2),
c = c(1,2,1,2,1,2,1,2))
df <- within(df, { f <- 1 / ave(b, list(c), FUN=length)})
df[, 1:3] <- lapply(df[, 1:3], as.factor)
ggplot(df, aes(x = b)) + geom_bar(stat = "identity", position = "stack",
aes(y = f, group = c, fill = a), binwidth = 1) + facet_wrap(~ c) +
scale_y_continuous(labels = percent_format())
This gives the plot:
Related
In the following plot, I want to rename x-axis by paste0 function.
daata <- data.frame(
q = paste0("q",1:20),
value = runif(n = 20, 2, 10))
ggplot2::ggplot(data = daata, aes(x = q, y = value)) +
geom_col()
so I used the following code:
q = paste0("q",1:20)
labels <- paste0("'", q,"'" , " = ", 1:20) %>% noquote()
# Or
labels <- noquote(paste0("'", q,"'" , " = ", 1:20))
ggplot2::ggplot(data = daata, aes(x = q, y = value)) +
geom_col() +
scale_x_discrete(labels = labels)
But it did not work. Why? (main question)
I want to search for solutions that make labels = c("'q1' = 1", ...) works.
Beside paste function I know two alternatives.
Using list:
labels = sapply(1:20, list)
names(labels) <- daata$q
ggplot2::ggplot(data = daata, aes(x = q, y = value)) +
geom_col() +
scale_x_discrete(labels = labels)
Using function:
ggplot2::ggplot(data = daata, aes(x = q, y = value)) +
geom_col() +
scale_x_discrete(labels = function(i){gsub("q", "", i)})
I am eager to know other solutions too.
How about something like this? Extract the question number in the data = step, and use that for the axis:
daata <- data.frame(
q = paste0("q",1:20),
value = 1:20)
ggplot2::ggplot(data = daata %>% mutate(order = str_remove(q, "q") %>% as.numeric),
aes(x = order, y = value)) +
geom_col() +
scale_x_continuous(breaks = 1:20, minor_breaks = NULL)
Edit: here's an alternative that extracts the numeric part of the label. As you'll note, this preserves the alphabetical ordering created by mapping x to q.
ggplot2::ggplot(data = daata, aes(x = q, y = value)) +
geom_col() +
scale_x_discrete(labels = function(x) parse_number(x))
why not giving a named vector?
labels <- parse_number(as.character(daata$q))
names(labels) <- as.character(daata$q)
p1 <- ggplot2::ggplot(data = daata, aes(x = q, y = value)) +
geom_col()
p2 <- p1 + scale_x_discrete(labels = labels)
cowplot::plot_grid(p1, p2, nrow = 1)
set.seed(357)
x <- data.frame(name = sample(letters, 10), val = runif(10), stringsAsFactors = F)
x[c(2,6),"name"] <- c("k","k")
ggplot(x, aes(x = name, y = val)) + theme_bw() + geom_bar(stat = "identity")
How can I plot the axis in the same order as x$name? (Yes, the k is duplicate, I want that to show up in the plot like this axis: c k g f o k s v t q)
In the past I used to do:
x$name <- factor(x$name, levels = x$name[order(x$val)], ordered = T)
wich doesn't work any more thanks to:
http://r.789695.n4.nabble.com/factors-with-non-unique-quot-duplicated-quot-levels-have-been-deprecated-since-2009-are-more-depreca-td4721481.html
This is no duplicate of: ggplot: order of factors with duplicate levels
His data structure is completely different.
Also, I have tried setting limits in x_scale_discrete. Doesn't work.
Try this...
x$name2 <- 1:nrow(x)
ggplot(x, aes(x = factor(name2), y = val)) + theme_bw() + geom_bar(stat = "identity") +
scale_x_discrete(labels=x$name)
Actually, simply add the following setting xlab(x$name)
ggplot(x, aes(x = name, y = val)) + theme_bw() + geom_bar(stat = "identity") + xlab(x$name)
I am trying to reproduce the simple population pyramid from the post Simpler population pyramid in ggplot2
using ggplot2 and dplyr (instead of plyr).
Here is the original example with plyr and a seed
set.seed(321)
test <- data.frame(v=sample(1:20,1000,replace=T), g=c('M','F'))
require(ggplot2)
require(plyr)
ggplot(data=test,aes(x=as.factor(v),fill=g)) +
geom_bar(subset=.(g=="F")) +
geom_bar(subset=.(g=="M"),aes(y=..count..*(-1))) +
scale_y_continuous(breaks=seq(-40,40,10),labels=abs(seq(-40,40,10))) +
coord_flip()
Works fine.
But how can I generate this same plot with dplyr instead? The example uses plyr in the subset = .(g == statements.
I have tried the following with dplyr::filter but got an error:
require(dplyr)
ggplot(data=test,aes(x=as.factor(v),fill=g)) +
geom_bar(dplyr::filter(test, g=="F")) +
geom_bar(dplyr::filter(test, g=="M"),aes(y=..count..*(-1))) +
scale_y_continuous(breaks=seq(-40,40,10),labels=abs(seq(-40,40,10))) +
coord_flip()
Error in get(x, envir = this, inherits = inh)(this, ...) :
Mapping should be a list of unevaluated mappings created by aes or aes_string
You avoid the error by specifying the argument data in geom_bar:
ggplot(data = test, aes(x = as.factor(v), fill = g)) +
geom_bar(data = dplyr::filter(test, g == "F")) +
geom_bar(data = dplyr::filter(test, g == "M"), aes(y = ..count.. * (-1))) +
scale_y_continuous(breaks = seq(-40, 40, 10), labels = abs(seq(-40, 40, 10))) +
coord_flip()
You can avoid both dplyr and plyr when making population pyramids with recent versions of ggplot2.
If you have counts of the sizes of age-sex groups then use the answer here
If your data is at the individual level (as yours is) then use the following:
set.seed(321)
test <- data.frame(v=sample(1:20,1000,replace=T), g=c('M','F'))
head(test)
# v g
# 1 20 M
# 2 19 F
# 3 5 M
# 4 6 F
# 5 8 M
# 6 7 F
library("ggplot2")
ggplot(data = test, aes(x = as.factor(v), fill = g)) +
geom_bar(data = subset(test, g == "F")) +
geom_bar(data = subset(test, g == "M"),
mapping = aes(y = - ..count.. ),
position = "identity") +
scale_y_continuous(labels = abs) +
coord_flip()
To build an Age Pyramid with individual data or microdata you can use:
test <- data.frame(v=sample(1:100, 1000, replace=T), g=c('M','F'))
ggplot(data = test, aes(x = v, fill = g)) +
geom_histogram(data = subset(test, g == "F"), binwidth = 5, color="white", position = "identity") +
geom_histogram(data = subset(test, g == "M"), binwidth = 5, color="white", position = "identity",
mapping = aes(y = - ..count.. )) +
scale_x_continuous("Age", breaks = c(seq(0, 100, by=5))) +
scale_y_continuous("Population", breaks = seq(-30, 30, 10), labels = abs) +
scale_fill_discrete(name = "Sex") +
coord_flip() +
theme_bw()
Changing the binwidth in geom_histogram() can group your data in wider categories.
Changing binwidth to 10 and adjusting the axis breaks:
ggplot(data = test, aes(x = v, fill = g)) +
geom_histogram(data = subset(test, g == "F"), binwidth = 10, color="white", position = "identity") +
geom_histogram(data = subset(test, g == "M"), binwidth = 10, color="white", position = "identity",
mapping = aes(y = - ..count.. )) +
scale_x_continuous("Age", breaks = c(seq(0, 100, by = 10))) +
scale_y_continuous("Population", breaks = seq(-100, 100, 10), labels = abs) +
scale_fill_discrete(name = "Sex") +
coord_flip() +
theme_bw()
I would like to plot a barplot but I have dates on the x axis and I want those dates to be correctly spaced (as it is NON categorical)
set.seed(1)
m = matrix(abs(rnorm(6)),3,2)
rownames(m) = as.Date(c('2011-01-01','2011-01-03','2011-01-10'))
barplot(t(m),beside=T,col=c('red','blue'),las=2)
On this example I would like 14984 to be offset on the right.
I'd rather a graphics solution but ggplot2 is fine too
Would you mind to use ´ggplot´ instead?
library(ggplot2)
set.seed(1)
df <- data.frame(y=abs(rnorm(6)),
x=rep(as.Date(c('2011-01-01','2011-01-03','2011-01-10')),
times = 2),
g = factor(rep(c(1,2), each = 3)))
ggplot(aes(x=x, y=y, group = g, fill = g), data = df) +
geom_bar(stat = 'identity', position = 'dodge')
You can improve axis formatting with `scale_x_date´
library(scales)
ggplot(aes(x=x, y=y, group = g, fill = g), data = df) +
geom_bar(stat = 'identity', position = 'dodge') +
scale_x_date(breaks = '1 day') +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5))
And customize it to your purpose
ggplot(aes(x=x, y=y, group = g, fill = g), data = df) +
geom_bar(stat = 'identity', position = 'dodge') +
scale_x_date(breaks = '1 day') +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5)) +
scale_fill_manual('My\nclasses', values = c('1'='red', '2' = 'blue')) +
labs(list(title = 'Barplot\n', x = ('Date'), y = 'Values'))
With graphics, you probably have to prepare the data appropriately (with missing values for dates you don't consider) in order to do this. Then you can use barplot.
# matrix definition
set.seed(1)
m = matrix(abs(rnorm(6)),3,2)
rownames(m) = as.Date(c('2011-01-01','2011-01-03','2011-01-10'))
# get all dates in between
dts <- do.call(":", as.list(range(rownames(m))))
dts <- dts[!dts%in%rownames(m)]
mat <- matrix(NA, nrow=length(dts), ncol=2, dimnames=list(dts, NULL))
# combine with original matrix
m <- rbind(m, mat)
m <- m[order(rownames(m)), ]
which(!is.na(m[,1]))
# plot
barplot(t(m), beside=T, col=c('red','blue'),las=2, axes=FALSE, axisnames=FALSE)
axis(2)
axis(1, at=3*which(!is.na(m[,1]))-1, labels=rownames(m[!is.na(m[,1]),]))
I was looking for a way to plot using facet_grid in ggplot2 that only displays just a few select facets. say I have the following plot:
Been looking for a quick way to, for instance, just plot facets 1 and 3.
#data
y<-1:12
x<-c(1,2,3,1,2,3,1,2,3,1,2,3)
z<-c("a","a","a","b","b","b","a","a","a","b","b","b")
df<-as.data.frame(cbind(x,y,z))
#plot
a <- ggplot(df, aes(x = z, y = y,
fill = z))
b <- a + geom_bar(stat = "identity", position = "dodge")
c <- b + facet_grid(. ~ x, scale = "free_y")
c
Obviously I figured out how to just chop up my data first but this must of course be possible to allocate in ggplot2 Even just a nudge would be most welcome.
Use subset in your ggplot call.
plot_1 = ggplot(subset(df, x %in% c(1, 2)), aes(x=z, y=y, fill=z)) +
geom_bar(stat = "identity", position = "dodge") +
facet_grid(. ~ x, scale = "free_y")
Would this be okay,
a <- ggplot(subset(df, x != 2), aes(x = z, y = y, fill = z))
b <- a + geom_bar(stat = "identity", position = "dodge")
c <- b + facet_grid(. ~ x, scale = "free_y")
c