Here is a pretty simple function.
-tgs
ColorBlocks <- function(rows, columns, ColorMatrix, RowNames, ColumnNames,
TextMatrix = NULL){
# This function takes the following inputs:
# rows : a numeric vector denoting the relative heights of rows
# columns : a numeric vector denoting the relative widths of columns
# ColorMatrix : a numeric matrix of integers representing colors
# RowNames : a character vector of row names
# ColumnNames : a character vector of column names
# TextMatrix : optional, a character matrix of text to print in the center
of each rectangle
# Colors are selected from palette(). To change colors, see help(palette).
rows <- rows / sum(rows)
columns <- columns / sum(columns)
old.pars <- par(no.readonly=TRUE)
LeftMargin <- max(strwidth(RowNames,"inches")) * 1.04
TopMargin <- max(strheight(ColumnNames,"inches")) * 1.4
par(tcl = 0, mgp c(1,.2,0),mai=c(0.04,LeftMargin,TopMargin,0.04),cex.axis=.8)
plot.new()
plot.window(xlim=c(0,1),ylim=c(-1,0),xaxs='i',yaxs='i')
rrr <- -c(0,cumsum(rows))
ccc <- c(0,cumsum(columns))
for(i in 1:nrow(ColorMatrix)){
for(j in 1:ncol(ColorMatrix)){
rect(ccc[j],rrr[i+1],ccc[j+1],rrr[i],col=ColorMatrix[i,j],border="white")
if(!is.null(TextMatrix[i,j])) text( mean(ccc[j:(j+1)]), mean(rrr[i:(i+1)]),
TextMatrix[i,j])
}
}
axis(2,at = -(cumsum(rows) + head(-rrr,-1))/2, labels RowNames,line=0,las=1)
axis(3,at = (cumsum(columns) + head(ccc,-1))/2, labels = ColumnNames)
box()
par(old.pars)
}
Z <- textConnection("
country TWh
Australia 244
Canada 522
China 3503
EU 2500
India 689.5
Japan 997
USA 3960
")
CountryEnergy <- read.table(Z,header=TRUE)
close(Z)
Z <- textConnection("
Product TWh
Freezer 72.4
Refrigerator 379
HVAC 466
Lighting 123
Television 152
")
ProductEnergy <- read.table(Z,header=TRUE)
close(Z)
#Generate Random Color Matrix
set.seed(325034)
RandomColors <- matrix(sample(1:100,35),nrow=7,ncol=5)
#Choose the entire palette of colors
palette(colors())
#
ColorBlocks(
rows = CountryEnergy[,2],
columns = ProductEnergy[,2],
ColorMatrix = RandomColors,
RowNames = CountryEnergy[,1],
ColumnNames = ProductEnergy[,1]
)
On Fri, Dec 14, 2012 at 4:12 PM, Neal Humphrey
<nhumphrey@clasponline.org>wrote:
> Your right, the way I’ve proposed the graphic it simplifies the story. In
> this graph, the size of the box is approximately how much energy that
> country uses for that appliance – but not exactly. For most appliances it
> should be an okay estimate, although for example air conditioners in Russia
> would be an exception. ****
>
> ** **
>
> I’m proposing this format mostly for readability – when there are 20-30
> countries and appliances, I’m concerned about misaligning the appliances
> from their labels. The main story I’m trying to tell with the graphic is
> how much standards coverage there is and for which appliances, while the
> amount of energy is a secondary variable. It’s also secondary because the
> actual energy savings potential from a standard will vary widely based on
> how strict the standard is. ****
>
> ** **
>
> I was planning to complement this with a treemap
graphic<http://flowingdata.com/2010/02/11/an-easy-way-to-make-a-treemap/>,
> where you trade off readability of the secondary category for accurate
> representation of per country per appliance energy use. ****
>
> ** **
>
> Talking through it now, maybe you’re right that just going with the
> Marimekko-like plot, with some careful formatting cleanup in Illustrator,
> is a better representation? I’d need to make some assumptions to fill holes
> in my data (it’s hard to get per country-per appliance data at the level of
> granularity I’m aiming for). ****
>
> ** **
>
> I’m open to critiques or suggestions about the approach. Either way, I
> still need to figure out how to do the true/false color coding so any
> pointers on that are welcome. ****
>
> ** **
>
> ** **
>
> ** **
>
> *Neal Humphrey*
>
> Tel: +1 202.662.7241 | Skype: neal.s.humphrey | nhumphrey@clasponline.org*
> ***
>
> www.clasponline.org****
>
> ** **
>
> ** **
>
> *From:* tgstewart@gmail.com [mailto:tgstewart@gmail.com] *On Behalf Of
*Thomas
> Stewart
> *Sent:* Friday, December 14, 2012 3:18 PM
> *To:* Neal Humphrey
>
> *Subject:* Re: [R] Combined Marimekko/heatmap****
>
> ** **
>
> Neal-****
>
> ** **
>
> Help me understand something: In my mind, the size of each box---say
> Country A, appliance A1---should communicate the percentage of (total)
> energy consumption in country A using appliance A1. They way you've
set up
> your plot does not do that. I guess my question is: What information does
> the size of the box communicate in your plot?****
>
> ** **
>
> I'd be happy to help once I understand.****
>
> ** **
>
> -tgs****
>
> ** **
>
> On Fri, Dec 14, 2012 at 1:03 PM, Neal Humphrey
<nhumphrey@clasponline.org>
> wrote:****
>
> Thomas,
>
> This is a big help for getting me started. Brand new to R, so I'm
> unfamiliar with how to 'manually' drawing graphs (instead of
packages).
>
> The graph your code makes is more like a Marimekko chart. What I'm
> thinking of is like a heatmap but each row has a different width, and each
> column has a different width. But, for any particular column, the width is
> the same all the way down.
>
> I used your code to figure out how to draw lines on a chart the way I need
> this to look. Now what I need to figure out is how to add color coding to
> the respective squares. In my example it's binary data (yes/no), but a
more
> robust approach would allow for a true heatmap.
>
> Any help on getting this to the next step of color coding would be much
> appreciated! The code below will draw a grid that is scaled per the sample
> data on the x and y axes. Perhaps what is needed is to draw boxes rather
> than lines to make the grid? I'm not sure.
>
> Neal****
>
>
> par(mar=c(1,1,1,1),
> oma = c(0,0,0,0),
> mgp=c(1.5,.2,0),
> tcl=0,
> cex.axis=.75,
> col.axis="black",
> pch=16)****
>
> #--------Input the sample data-------------------
> Z <- textConnection("
> country TWh
> Australia 244
> Canada 522
> China 3503
> EU 2500
> India 689.5
> Japan 997
> USA 3960
> ")
> CountryEnergy <- read.table(Z,header=TRUE)
> close(Z)
>
> Z <- textConnection("
> Product TWh
> Freezer 72.4
> Refrigerator 379
> HVAC 466
> Lighting 123
> Television 152
> ")
> ProductEnergy <- read.table(Z,header=TRUE)
> close(Z)
>
> #-------------Binary data indicating whether that country/product
> combination has a standard----------------
> #-------------Rows correspond to countries (in the same order as the
> CountryEnergy matrix)------------------
> #-------------Columns correspond to products (in the same order as the
> ProductEnergy matrix)----------------
> Z <- textConnection("
> country TWh
> 0 1 0 0 1
> 0 1 1 1 0
> 1 0 1 0 0
> 1 1 1 0 0
> 0 1 1 1 1
> 1 0 0 0 1
> 1 0 0 0 0
> ")
> ddd <- read.table(Z,header=FALSE)
> close(Z)
>
> #-----------rewrite the data table so that the vector is numbers only, and
> label the rows----------
> row.names(CountryEnergy) <- CountryEnergy$Country
> CountryEnergy<-CountryEnergy[,2:2]
> row.names(ProductEnergy) <- ProductEnergy$Product
> ProductEnergy <- ProductEnergy[,2:2]
>
>
> #-----------plot the grid------------
> plot.new()
> plot.window(ylim=c(0,sum(CountryEnergy)),xlim=c(0,sum(ProductEnergy)),xaxs
> = 'i',yaxs='i',las=1)
> box()
> abline(h = cumsum(CountryEnergy),lwd=2, col="gray60") #lwd -
line width
> abline(v = cumsum(ProductEnergy), lwd=2, col="gray60")
>
> labxats <- NULL
>
> #----------Use ddd data to code the cells as yes/no for having a
> standard---------------------
> #
> #
> # this is the part I need help with
> #
> #
> #
>
>
#----------------------------------------------------------------------------------------------
>
>
> Neal Humphrey
> nhumphrey@clasponline.org
>
> From: Thomas Stewart [mailto:tgs@live.unc.edu]
> Sent: Friday, December 14, 2012 10:36 AM
> To: Neal Humphrey
> Cc: r-help@r-project.org
> Subject: Re: [R] Combined Marimekko/heatmap****
>
>
> Neal-
>
> Perhaps the following code is a start for what you want.
>
> -tgs
>
> par(mar=c(1,1,1,1),
> oma = c(0,0,0,0),
> mgp=c(1.5,.2,0),
> tcl=0,
> cex.axis=.75,
> col.axis="black",
> pch=16)
>
> Z <- textConnection("
> country A1 A2 A3
> A 3 4 5
> B 6 9 8
> C 6 9 5")
> ddd <- read.table(Z,header=TRUE)
> close(Z)
>
>
> CountryPcts <- rowSums(ddd[,-1]) / sum(ddd[,-1])
>
> plot.new()
> plot.window(ylim=c(0,1),xlim=c(0,1),xaxs =
'i',yaxs='i',las=1)
> box()
> abline(h = cumsum(CountryPcts),lwd=2)
>
> labxats <- NULL
> vlines <- ddd[,-1] / sum(ddd[,-1]) / CountryPcts
> vlines <- t(apply(vlines,1,cumsum))
> yyy <- c(0,rep(cumsum(CountryPcts),each=2))
> yyy <- head(yyy,-1)
> for(i in 1:nrow(ddd) ){
> xxx <- rep(vlines[,i],each=2)
> lines(xxx,yyy,col="red",lwd=3)
> labxats[i] <- rev(xxx)[1]
> }
>
> labxats <- (labxats + c(0,head(labxats,-1)))/2
> labyats <- (cumsum(CountryPcts) + c(0,head(cumsum(CountryPcts),-1)))/2
> axis(2,at=labyats,labels = ddd[,1],las=1 )
> axis(3,at=labxats,labels = colnames(ddd)[-1],las=1 )
>
> On Thu, Dec 13, 2012 at 6:09 PM, Neal Humphrey
<nhumphrey@clasponline.org>
> wrote:
> Hi all,
>
> I'm trying to figure out a way to create a data graphic that I
haven't
> ever seen an example of before, but hopefully there's an R package out
> there for it. The idea is to essentially create a heatmap, but to allow
> each column and/or row to be a different width, rather than having uniform
> column and row height. This is sort of like a Marimekko chart in
> appearance, except that rather than use a single color to represent the
> category, the color represents a value and all the y-axis heights in each
> column line up with each other. That way color represents one variable,
> while the area of the cell represents another.
>
> In my application, my heatmap has discrete categorical data rather than
> continuous. Rows are countries, columns are appliances, and I want to scale
> the width and height of each column to be the fraction of global energy
> consumed by the country and the fraction of energy use consumed by that
> appliance type. The color coding would then indicate whether or not that
> appliance is regulated in that country.
>
> Any ideas how to make such a chart, or even what it might be called?
>
>
> Neal Humphrey
> NHumphrey@clasponline.org
>
> ______________________________________________
> R-help@r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide
> http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
>
>
>
> ****
>
> ** **
>
[[alternative HTML version deleted]]