Category Archives: Tricks

Finally, an easy way to fix the horizontal lines in ggplot2 maps

ggplot2 tries to make it super easy to add country or state borders to your map, and for the most part it works great as long as you include the entire map region in your plot (all the states or the entire world map for example). A long standing issue with the ggplot2 borders() function is when you try and zoom in a way that removes data outside of the plotting region, countries and states get cut off and not reconnected correctly, resulting in spurious horizontal lines in the plot. A forum post and ggplot2 issue both allude to this problem.

Here is a simple example showing this issue. First, a simple unprojected map that looks great because we are not trying to zoom in at all.

ggplot() +
    borders("world") + borders("state") +
    theme_bw()

Alt text

An obvious extension would be to zoom in on a region and project the map:

ggplot() +
    borders("world") + borders("state") +
    theme_bw() +
    coord_map(xlim=xlim,ylim=ylim) +
    labs(y="",x="")

Alt text

Which pretty clearly illustrates the issue. Things look even worse if we try and add color:

ggplot() +
    borders("world",fill="darkseagreen") +
    borders("state",fill="darkseagreen") +
    theme_bw() +
    coord_map(xlim=xlim,ylim=ylim) +
    labs(y="",x="")

Alt text

The underlying issue is that when we zoom with coord_map() the polygons get cut up, with some parts appearing on either side of the map, hence the horizontal lines when ggplot tries to connect a country or state that appears on two sides of the map. The solution to this issue is to get the raw map data then use one of the various polygon clipping libraries in R. I used PBSmapping. Here is a complete example

library("PBSmapping")
library("ggplot2")
library("maps")
library("data.table")

# plot limits
xlim = c(-165,-90)
ylim = c(10,60)

worldmap = map_data("world")
setnames(worldmap, c("X","Y","PID","POS","region","subregion"))
worldmap = clipPolys(worldmap, xlim=xlim,ylim=ylim, keepExtra=TRUE)

statemap = map_data("state")
setnames(statemap, c("X","Y","PID","POS","region","subregion"))
statemap = clipPolys(statemap, xlim=xlim,ylim=ylim, keepExtra=TRUE)

p = ggplot() +
    coord_map(xlim=xlim,ylim=ylim) +
    geom_polygon(data=worldmap,aes(X,Y,group=PID),
        fill = "darkseagreen",color="grey50") +
    geom_polygon(data=statemap,aes(X,Y,group=PID),
        fill = "darkseagreen",color="grey50") +
    labs(y="",x="") +
    theme_bw()
 print(p)

Alt text

This could also be used to fix the fill issues when doing ggplot filled contour plots.

Using tikzDevice with Sweave in R 2.13

R 2.13 introduces an option to specify a custom graphics device in an Sweave code chunk. This is really cool and allows you to use tikzDevice output like pgfSweave does. In an pinch, say when you dont have access to any non-core packages, you can use tikzDevice output with the regular Sweave driver (RweaveLatex) more simply than before. Here is a minimal example showing how.

\documentclass{article}

\usepackage[noae,nogin]{Sweave}
\usepackage{tikz}



\begin{document}
\SweaveOpts{prefix.string=fig}

Example using \texttt{tikzDevice} with the default \textbf{Sweave}
driver (\texttt{RweaveLatex}).  First define a custom device:

<<results=hide>>=
tikz.Swd <- function(name, width, height, …){
    require(tikzDevice)
    tikzDevice::tikz(file = paste(name, "tikz", sep = "."),
                 width = width, height = height)

}
@

Then use the device for plotting, but you have to include the figure manually.

<<myplot, fig=T, grdevice=tikz.Swd, include=F, width=4,height=4>>=
plot(1)
@
\input{fig-myplot.tikz}


\end{document
}

WARNING: This could be very slow if your graphic is complex

No Sidebar, Fullscreen, Super Minimal Gmail (for ninjas)

Real Gmail Ninjas dont want all that sidebar clicky junk on their screens. Because of keyboard shortcuts, you can do nearly everything in Gmail with the keyboard and the sidebar becomes irrelevant. Also I use Adium, so I don’t need the build in chat.

I created a css file that kills the sidebar and some other things:

  • Inbox spans full screen
  • Extra attachment icons
  • No ads
  • Messages span whole screen
  • No footer

Please hack away. This script has pieces cobbled from various user scripts and extensions, I am really sorry but I don’t remember all my sources, please call me out on that.

Get it here.

UPDATE: Gmail changed some things, so I updated the css file fo fix some weirdness. It also now works with viewing contacts!