views:

261

answers:

3

I've been trying to create a 3D bar plot based on categorical data, but have not found a way.

It is simple to explain. Consider the following example data (the real example is more complex, but it reduces to this), showing the relative risk of incurring something broken down by income and age, both categorical data.

I want to display this in a 3D bar plot (similar in idea to http://demos.devexpress.com/aspxperiencedemos/NavBar/Images/Charts/ManhattanBar.jpg). I looked at the scatterplot3d package, but it's only for scatter plots and doesn't handle categorical data well. I was able to make a 3d chart, but it shows dots instead of 3d bars. There is no chart type for what I need. I've also tried the rgl package, but no luck either. I've been googling for more than an hour now and haven't found a solution. I have a copy of the ggplot2 - Elegant Graphics for Data Analysis book as well, but ggplot2 doesn't have this kind of chart.

Is there another freeware app I could use? OpenOffice 3.2 doesn't have this chart either.

Thank you for any hints.

Age,Income,Risk
young,high,1
young,medium,1.2
young,low,1.36
adult,high,1
adult,medium,1.12
adult,low,1.23
old,high,1
old,medium,1.03
old,low,1.11
+4  A: 

I'm not sure how to make a 3d chart in R, but there are other, better ways to represent this data than with a 3d bar chart. 3d charts make interpretation difficult, because the heights of the bars and then skewed by the 3d perspective. In that example chart, it's hard to tell if Wisconsin in 2004 is really higher than Wisconsin 2001, or if that's an effect of the perspective. And if it is higher, how much so?

Since both Age and Income have meaningful orders, it wouldn't be awful to make a line graph. ggplot2 code:

ggplot(data, aes(Age, Risk, color = Income))+
  geom_line(aes(group = Income))

Or, you could make a heatmap.

ggplot(data, aes(Age, Income, fill = Risk)) +
  geom_tile()
JoFrhwld
You're fundamentally right about the 3d chart not being as good for visualization (i.e. it's 'chartjunk'). It's just that for the particular data I have it fitted the bill, it happens that it's like a hill so I could put the highest x-y combination in the remote corner. I'll probably fall back to the line chart even though with some reluctance because it assumes a progression on only one dimension (in the example, age) while income is coloured. Since these are categoricals, I could also reverse colour and age. A 3d chart would have been neutral. Thanks, though.
wishihadabettername
A: 

You can find a starting point here but you need to add in more lines and some rectangles to get a plot like you posted.

John
I had seen it, but couldn't figure a way to fill the square completely; the bars are still plotted only at the intersection of grid lines, with large areas in between.
wishihadabettername
+1  A: 

Like the others suggested there are better ways to present this, but this should get you started if you want something similar to what you had.

df <-  read.csv(textConnection("Age,Income,Risk
young,high,1
young,medium,1.2
young,low,1.36
adult,high,1
adult,medium,1.12
adult,low,1.23
old,high,1
old,medium,1.03
old,low,1.11
"))
df$Age <- ordered(df$Age, levels=c('young', 'adult', 'old'))
df$Income <- ordered(df$Income, levels=c('low', 'medium', 'high'))
library(rgl)
plot3d(Risk ~ Age|Income, type='h', lwd=10, col=rainbow(3))

This will just produce flat rectangles. For an example to create nice looking bars, see demo(hist3d).

DiggyF
I tried the demo as well, but unfortunately the demo uses the hist3d function, there is no barplot3d. It's been requested in the past (http://www.mail-archive.com/[email protected]/msg01084.html) but there is no implementation yet. I guess this is it.
wishihadabettername