I've put together an R function for drawing a basic map of the market.   
It's designed to take data from a portfolio object, but the variables  
can also be set manually to any appropriate data vectors.  Credit goes  
to David Brahm for writing the code underlying the treemap algorithm.   
Also thanks to John Bollinger, Bill Rugolsky,  Peter Carl, Vincent, and  
Achim Zelleis for valuable background on treemaps, and to David Kane  
for giving me this project.  The code is below, followed by a short  
example.

-Kyle Campbell


######################################################################## 
########
##
## $Id: $
##
## Plot a "map" of a given portfolio, based on the Map of the Market
##
######################################################################## 
########

## "x" is an object of class portfolio; if x is not provided, each of  
the four
## variables must be supplied as lists or vectors of equal length.   
"id.var"
## stores the labels for each stock.  "area.var" stores the values used  
to
## compute the area of rectangles in the map (this can be anything, but  
defaults
## to the weights slot).  "sector.var" stores the sector of each stock.
## "color.var" stores the values used to compute the color of the  
rectangles,
## usually the ret.var of the portfolio.  If specifying both "x" and  
some of the
## variables, the actual location of the data must be provided (not  
just a
## column name in x@data).  "lab" specifies whether labels should be  
printed.

## Because the default settings access the data slot of "x" directly,  
they will
## break if there are more stocks in data than in the actual portfolio.  
  This
## should be fixed.

map.market <- function(x, id.var = x@data[[x@id.var]], area.var =  
x@weights$weight,
                        sector.var = x@data$sector, color.var =  
x@data[[x@ret.var]],
                        lab = TRUE){

   if(any(length(id.var) != length(area.var), length(id.var) !=  
length(sector.var),
                  length(id.var) != length(color.var))){
     stop("id.var, area.var, sector.var, and color.var must be the same  
length.")
   }

   ## Most extreme color should be either 1 or -1; all others are scaled  
accordingly
   color.scalar <- 1/max(abs(max(color.var)), abs(min(color.var)))
   color.var <- color.var * color.scalar

   ## Formatting the data
   data <- data.frame(id.var, sector.var, area.var, color.var)
   names(data) <- c("label", "sector", "area", "color")
   data <- data[order(data$area, decreasing =TRUE),]

   data.by.sector <- split(data, data$sector, drop=TRUE)

   sector.data <- lapply(data.by.sector, function(x){sum(x[,3])})
   sector.data <- data.frame(as.numeric(sector.data), names(sector.data))
   names(sector.data) <- c("area", "label")
   sector.data <- sector.data[order(sector.data$area, decreasing=TRUE),]
   sector.data$color <- rep(NULL, nrow(sector.data))

##   ## Defines the color palettes
##   pos.palette <- colorRamp(c("black", "green"), bias = 20, space =  
"rgb",
##                                   interpolate = "spline")
##   neg.palette <- colorRamp(c("black", "red"), bias = 20, space =  
"rgb",
##                                   interpolate = "spline")

   ## Accepts the current viewport list and parameters for the next  
viewport
   ## Returns the viewport list with the next viewport appended to it

   add.viewport <- function(z, label, color, x.0, y.0, x.1, y.1,  
lab=TRUE){

     i <- 1
     while(i <= length(label)){

       ## Sectors are black, positive change is green, negative change  
is red
       ## Alpha level determines color saturation
       if(is.null(color[i])){
         filler <- gpar(col="blue", fill="transparent", fontsize=12)
       }
       else{
         if(color[i] < 0){
           filler <- gpar(col = rgb(abs(color[i]),0,0), fill =  
rgb(abs(color[i]),0,0),
                          fontsize=10)
         }
         else{
           filler <- gpar(col = rgb(0,color[i],0), fill =  
rgb(0,color[i],0),
                          fontsize=10)
         }
       }

       ## Viewport created from squarified treemap specifications
       new.viewport <- viewport(x = x.0[i], y = y.0[i], width =
                                (x.1[i] - x.0[i]), height = (y.1[i] -  
y.0[i]),
                                default.units = "npc", just = c("left",  
"bottom"),
                                name = as.character(label[i]), clip =  
"on",
                                gp = filler)

       pushViewport(new.viewport)
       grid.rect()
       if(lab){
         grid.text(label = as.character(label[i]), x = .5, y = .5,
                   default.units = "npc", just =  "center", gp =  
gpar(col="white"))
       }
       popViewport()

       z <- append(z, list(new.viewport))

       i <- i+1
     }
     z
   }

   ## Recursive function that returns a complete list of viewports,
   ## in the order they should be plotted.
   ## "z" should be a data frame with columns "area", "label", and  
"color",
   ## sorted in descending order by "z$area"; "viewport.list" should be  
an
   ## initially empty list; func should be the "add.viewport" function  
defined above

   squarified.treemap <- function(z, x = 0, y = 0, w = 1, h = 1, func =  
add.viewport,
                                  viewport.list, lab = TRUE){

     ## "cz" stores cumulative percentages of the total area
     cz <- cumsum(z$area) / sum(z$area)

     ## "n" marks where to break this region
     n <- which.min(abs(log(max(w/h, h/w) * sum(z$area) *  
((cz^2)/z$area))))

     ## do we have any left-over rectangles?
     more <- n < length(z$area)

     ## "a" stores cumulative percentages for this region
     a <- c(0, cz[1:n]) / cz[n]

     ## Determines the direction in which we are adding rectangles
     if (h > w){

       ## Calls the add.viewport function n times, adding each
       ## rectangle to "viewport.list"
       viewport.list <- func(viewport.list, z$label[1:n], z$color[1:n],
                             x+w*a[1:(length(a)-1)], rep(y,n), x+w*a[-1],
                             rep(y+h*cz[n],n), lab)

       ## Recursive call, in case there are more regions
       if(more){
         viewport.list <- Recall(z[-(1:n), ], x, y+h*cz[n], w,  
h*(1-cz[n]), func,
                                 viewport.list, lab)
       }
     }
     else{
        viewport.list <- func(viewport.list, z$label[1:n], z$color[1:n],  
rep(x,n),
                              y+h*a[1:(length(a)-1)], rep(x+w*cz[n],n),  
y+h*a[-1], lab)
       if(more){
         viewport.list <- Recall(z[-(1:n), ], x+w*cz[n], y, w*(1-cz[n]),  
h,
                                 func, viewport.list, lab)
       }
     }
     viewport.list
   }

   ## Viewport to hold the map of the market
   grid.rect(gp=gpar(col="dark gray", fill="dark gray"))
   pushViewport(viewport(x=.05, y=.05, width=.9, height=.75,  
default.units="npc",
                         name="MAP", just=c("left", "bottom")))
   grid.rect(gp=gpar(col = "black"))

   ## Draw sector viewports
   sector.viewports <- list()
   sector.viewports <- squarified.treemap(z=sector.data,
                                          viewport.list =  
sector.viewports, lab = lab)

   ## Fill in each sector
   i = 1
   while(i <= length(sector.viewports)){
     this.sector <- data.by.sector[[sector.data$label[i]]]
     this.data <- data.frame(this.sector$area, this.sector$label,
                             this.sector$color)
     this.list <- list()

     pushViewport(sector.viewports[[i]])
     squarified.treemap(z=this.sector, viewport.list = this.list,  
lab=lab)
     grid.rect(gp=gpar(col="white"))
     if(lab){
       grid.text(label=sector.data$label[i])
     }
     popViewport()
     i <- i+1
   }
   popViewport()

   ## Viewport to hold legend
   pushViewport(viewport(x=0, y=.8, width=1, height=.2,  
default.units="npc",
                         name="LEGEND", just=c("left", "bottom")))
   grid.rect(x=.5, y=.5, width=.3, height=.3, default.units="snpc",
             gp=gpar(col="red", fill="red"))
   grid.text(label= as.character(format(-1 * (1/color.scalar),  
digits=4)),
             x=1, y=.5, default.units="snpc", gp=gpar(col="black"))
   grid.rect(x=2.25, y=.5, width=.3, height=.3, default.units="snpc",
             gp=gpar(col="black", fill="black"))
   grid.text(label= as.character(format(0, digits=2)),
             x=2.75, y=.5, default.units="snpc", gp=gpar(col="black"))
   grid.rect(x=4, y=.5, width=.3, height=.3, default.units="snpc",
             gp=gpar(col="green", fill="green"))
   grid.text(label= as.character(format((1/color.scalar), digits=4)),
             x=4.5, y=.5, default.units="snpc", gp=gpar(col="black"))
   popViewport()

}

[end code]


The very basic example below maps a portfolio of 30 stocks, all with  
equal weights:

 > library(portfolio)
 > data(dow.jan.2005)
 > p <- new("portfolioBasic", id.var="symbol", in.var="price",  
sides="long",
					ret.var="month.ret", size=30, data=dow.jan.2005)
 > map.market(p)


For a slightly more interesting map, we can set area.var to "price":

 > map.market(p, area.var=p@data$price)

	[[alternative text/enriched version deleted]]

