geom_bar: stacking, and labelling, while comparing 2 years of data

467 views
Skip to first unread message

Brandon Bertelsen

unread,
Feb 2, 2011, 6:36:53 PM2/2/11
to ggp...@googlegroups.com
Hello ggploters,

I'm creating 100% stacked bars, as shown here
(http://www.bertelsen.ca/R/ggplot2-group/example 1.jpg
<http://www.bertelsen.ca/R/ggplot2-group/example%201.jpg>) I've had to
fuzz a few things out because the data is proprietary.

What I would like to do, is stack 2010 and 2011 bars on top of each
other. Kind of like this
(http://www.bertelsen.ca/R/ggplot2-group/example 2.jpg
<http://www.bertelsen.ca/R/ggplot2-group/example%202.jpg>) but rotated
90% and with labels accompanying each bar segment with the rel
proportion of the total bar.

Here is the code from my best attempt (produces example 2, above).
Unfortunately, I can only provide the structure of my data.frame, I
can't provide actual numbers:

str(df.tmp)

'data.frame': 240 obs. of 7 variables:
$ variable: Factor w/ 30 levels "1","2","3","4",..: 1 1 1 1 2 2 2 2 29
29 ... # A company name
$ value : Factor w/ 4 levels "1","2","3","4": 1 2 3 4 1 2 3 4 1 2
... # The respondents selection
$ frequ : num 67 125 74 15 42 116 137 47 4 20 ... # Frequency of
respondent selection
$ cfreq : num 0.238 0.683 0.947 1 0.123 ... # Cumulative frequency
for bar positioning
$ pos : num 0.1192 0.4609 0.8149 0.9733 0.0614 ... # Again, bar
positioning
$ freq : num 0.2384 0.4448 0.2633 0.0534 0.1228 ... #
$ year : Factor w/ 2 levels "2010","2011": 1 1 1 1 1 1 1 1 1 1 ...

My code:

panel.1 <- list(opts(panel.background=theme_blank(),
panel.grid.minor=theme_blank(), panel.grid.major=theme_blank(),
axis.text.x=theme_blank(), legend.position="right",
axis.ticks=theme_blank())

plot.tmp <- ggplot(df.tmp, aes(year,frequ, fill=value)) +
geom_bar(stat="identity", position="fill") +
scale_y_continuous("", formatter="percent") +
geom_bar(position="dodge") +
labs(x="",y="", fill="") +
panel.1 +
opts(title="Work Damnit!") +
facet_grid(. ~ variable)

Now this works, but adding labels (as follows) to the plot breaks the
output with an error message.

+ geom_text(data=df.tmp, size=3 ,aes(variable,pos, label=ifelse(freq*100
> 4,paste(round(freq*100,digits=0),"%",sep=""),"")))

Help is much appreciated!

Brandon Hurr

unread,
Feb 3, 2011, 5:20:48 AM2/3/11
to Brandon Bertelsen, ggp...@googlegroups.com
Making up data that fits together like your data is proving quite difficult... especially the pos and frequency information. If you can't provide the data, can you either make something up or tell us how you computed pos, cfreq, freq, and frequ? 

Speaking of proprietary data... Is there a function that we blasted industry people could use to mix our data up and/or rename variables to something random so that if it is the data structure that is the problem then others can help figure this out? 

Finally, and this is just way out there thinking since I haven't been able to try it with your data yet, but could you do something like linetype=year in geom_bar() and tell it to leave it out of the legend. The other option I see is faceting by "company" with year on the x-axis.  I think if either way works, it'll probably break your labeling or geom_text will require the use of the width argument. 

B


--
You received this message because you are subscribed to the ggplot2 mailing list.
Please provide a reproducible example: http://gist.github.com/270442

To post: email ggp...@googlegroups.com
To unsubscribe: email ggplot2+u...@googlegroups.com
More options: http://groups.google.com/group/ggplot2

Brandon Bertelsen

unread,
Feb 3, 2011, 5:45:22 AM2/3/11
to Brandon Hurr, ggp...@googlegroups.com
The best I can do is provide you with the syntax that creates the data frame that I'm plotting and a bit of dummy data:

df.tmp <- data.frame(rep(letters[1:10],100), rep(1:4,250))
colnames(df.tmp) <- c("value","variable")
df.tmp <- cast(df.tmp, variable + value ~ ., length, fill=c(0), add.missing=T)
colnames(df.tmp)[3] <- c("frequ")

df.tmp <- ddply(df.tmp,"variable", function(x) {
        x <- x[order(x$value),]
        x$cfreq <- cumsum(x$frequ)/sum(x$frequ)
        x$pos <- (c(0,x$cfreq[-nrow(x)])+x$cfreq)/2
        x$freq <- (x$frequ)/sum(x$frequ)
        x
    })

df.tmp1 <- data.frame(df.tmp, year=2010)
df.tmp2 <- data.frame(df.tmp, year=2011)

df.tmp <- rbind(df.tmp1, df.tmp2)

panel.1 <- list(opts(panel.background=theme_blank(), panel.grid.minor=theme_blank(), panel.grid.major=theme_blank(), axis.text.x=theme_blank(), legend.position="right", axis.ticks=theme_blank()))

plot.tmp <- ggplot(df.tmp, aes(year,frequ, fill=value)) + geom_bar(stat="identity", position="fill") + scale_y_continuous("", formatter="percent") + geom_bar(position="dodge")  + labs(x="",y="", fill="") + panel.1 + opts(title="Work Damnit!") + facet_grid(. ~ variable)

Brandon Bertelsen
Office: 647-722-0481 
Cell: 647-287-1009

Brandon Hurr

unread,
Feb 3, 2011, 6:36:24 AM2/3/11
to Brandon Bertelsen, ggp...@googlegroups.com
Brandon, 

Here is what I did with the example data... 

ggplot(df.tmp, aes(factor(year),freq, fill=value)) + 
geom_bar(stat="identity", position=c("stack")) + 
facet_grid(. ~ variable)+
geom_text(data=df.tmp, size=3 ,aes(factor(year), pos, label=ifelse(freq*100 > 4,paste(round(freq*100,digits=0),"%",sep=""),"")))+
scale_y_continuous("", formatter="percent") + 
labs(x="",y="", fill="") + 
opts(title="Work Damnit!"
, panel.background=theme_blank()
, panel.grid.minor=theme_blank()
, panel.grid.major=theme_blank()
, axis.text.x=theme_blank()
, legend.position="right"
, axis.ticks=theme_blank())

Is this close or am I missing the mark? 

B
colorfulstack.png

Brandon Bertelsen

unread,
Feb 3, 2011, 6:48:43 AM2/3/11
to Brandon Hurr, ggp...@googlegroups.com
It's beautiful! Thanks bunches!

Now this brings another question, is there a way to force it to wrap around again after let's say 10 columns?

Brandon Hurr

unread,
Feb 3, 2011, 6:53:11 AM2/3/11
to Brandon Bertelsen, ggp...@googlegroups.com
Brandon, 

I've been thinking some more on it and I'm not sure I did it right. You're coloring by variable with 4 levels, and I accidentally did it by "value" with many more levels. 

ggplot(df.tmp, aes(factor(year),frequ, fill=variable)) + 

geom_bar(stat="identity", position=c("stack")) + 

facet_grid(. ~ value)+

geom_text(data=df.tmp, size=3 ,aes(factor(year), freq, label=ifelse(freq*100 > 4,paste(round(freq*100,digits=0),"%",sep=""),"")))


When I switch the two, the locations of the text annotations don't work right, perhaps they need to be calculated differently? 


Good luck, 


B

Reply all
Reply to author
Forward
0 new messages