Weather surface plots with R


This code will help you make surface temperature (or dew point) plots. It is designed for the state of Florida, but with some modifications, you can use a different state.

I know, I know… Comic Sans is a bit bubbly, and maybe a tad unprofessional. But, this plot is cute, and it was meant for social media and auto-tweeting. You can, of course, use your favorite font 🙂

Side note. To use the font of your choice, you will need the extrafont package.

Step 1: We gotta download the necessary data.

  • The first is GIS data. Go to this website and download “SE 1 SHP Maps s_28au12.7z” – you will need to uncompress the files. I know this can be done in R, but I was struggling with that part. Lemme know if there is a simple way.
  • Then download the .csv files ‘merged.csv’ and ‘fl.merged.csv’





Step 2: Get to coding.

###Lisa Vaughn

###I honestly do not know if I need ALL of these packages.
#But I am scared to delete one of them.
#You know how it is... Sorry.
#The first time you install the extrafont package, you will
#need to type font_import() into the command line.
#You don't have to do this - you can use the default font.
#See this link for help on fonts.
#library(twitteR) If you want to tweet out your plot!

#Get the date. We'll use this later for the plot.
date         <- format(Sys.time(), "%b %d, %Y %I%p %Z")

#fl.merged is a subset of merged. I handpicked the cities I wanted to use.
#If you want to do Texas, for example, you will simply need to create a subset of merged.csv
#containing the Texas cities you want to use.
#There *will*, however, be other modifications to make if you choose a different state.
#You will see in the comments below.
fl.merged          <- read.csv("C:/Users/Lisa/Desktop/currents/fl.merged.csv",
                               stringsAsFactors = FALSE)

fl.merged$dewpoint <- rep(NA, nrow(fl.merged)) #create a column for dewpoint
fl.merged$temp     <- rep(NA, nrow(fl.merged)) #create a column for temp
total              <- nrow(fl.merged)

#Set up a progress bar for our 'for' loop.
pb                 <- txtProgressBar(min = 0, max = total, style = 3)

#This 'for' loop will collect the temp and dew point for each of the cities in our
#fl.merged .csv file.
for(i in 1:total){

  link        <- paste("", paste(fl.merged[i,1], ".html", sep = ""), sep ="")
  doc         <- html(link)
  tables      <- doc %>% html() %>% html_nodes(xpath = "/html/body/table") %>% html_table(fill = TRUE)

  data        <- data.frame(tables[[4]], stringsAsFactors = FALSE)

  #I realize this next step is not entirely necessary, but it's good to give the columns names
  #in case you want to use other variables in the future.
  names(data)          <- c("date", "time", "wind", "vis", "weather", "sky",
                            "temp", "dp", "6hrmax", "6hrmin", "rh", "windchill",
                            "heatindex", "altimeter", "sealevel_mb", "precip1", "precip2",

  num.rows              <- nrow(data)

  data                  <- data[-c(1,2,(num.rows-2):num.rows), ]  #Get rid of first two rows.
  new.num.rows          <- nrow(data)
  data                  <- data[(new.num.rows:1),] #re-order data.  Earliest obs first.

  fl.merged$temp[i]     <- data$temp[7] #Add temp to fl.merged
  fl.merged$dewpoint[i] <- data$dp[8]   #Add dew point to fl.merged

  setTxtProgressBar(pb, i) #This is for the progress bar.
close(pb) #closing the progress bar.    <- map('state', 'florida', fill = FALSE, plot = FALSE) #Get the lon/lat for outline of florida.

#Read in the GIS data. This takes a little bit of time.
state     <- readOGR("C:/Users/Lisa/Documents/Weather/Weather/SE 1 SHP Maps s_28au12/s_28au12",
                     "s_28au12", verbose = FALSE)

fl        <- state[state$STATE == "FL", ] #pick out just florida data

xyz       <- data.frame(-fl.merged$long, fl.merged$lat, fl.merged$dewpoint)
#xyz is a data frame with 3 columns: x axis, y axis, and the variable we are trying to plot (dew point or temperature)
#So, to plot temperature, we would have to change the fl.merged$dewpoint to fl.merged$temperature

mba.bbox  <- c(-89, -79, 25, 32) #These are the axes limits for the plot (in this case, lon & lat)

#surf stands for 'surface' (comes from MBA package)
surf.w                  <-, 150, 150, extend = TRUE,
                                    sp = TRUE, = mba.bbox)$xyz.est  #The 150,150 is the resolution. Make smaller to speed up processing time.

surf.w@data             <- surf.w@data * (!, fl)))
surf.w$z[surf.w$z == 0] <- NA
surf.w$z                <- surf.w$z * .010 #2.23693629

png("C:/Users/Lisa/Desktop/currents/current.temps.png") #where we want to save the image.
par(mar=rep(1,4), bg = "#43a2ca")
image(as.image.SpatialGridDataFrame(surf.w), asp = 1.25,
      col = rev(heat_hcl(10)),
      axes = FALSE, #set axes=TRUE if you want to see the lat/lon
      xlim = c(-87, -80))  #From the 'fields' package.

#Can use image.plot() instead of just image() to get a legend on the side.
plot(fl, add = TRUE)

text(-fl.merged$long + .25, fl.merged$lat + 0.25, label = fl.merged$STATION,
     cex = .75, family = "Comic Sans MS", font = 2)

text(-fl.merged$long + 0.25, fl.merged$lat, label = fl.merged$dewpoint,
     cex = 1.25, family = "Comic Sans MS", font = 2)

text(-83, 31.55, "Current Dew point", family = "Comic Sans MS", font = 2,
     cex = 2.25)

text(-83, 31.1, date, family = "Comic Sans MS")

I know there is always a more elegant and succinct way of writing code. Feel free to share with me how you made it better 🙂

Happy coding.

One thought on “Weather surface plots with R

Add yours

  1. Miss you in South Florida, Lisa! Was out of town for last day on air. Hopes and prayers are with you. Congrats on your forthcoming nuptials!


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at

Up ↑

%d bloggers like this: