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’

 

current.temps

 

 

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.
library(httr)
library(rvest)
require(httpuv)
library(fields)
library(maps)
library(MBA)
library(spdep)
library(sp)
library(utils)
library(R.utils)
library(rgdal)
library(extrafont)
#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.
#http://blog.revolutionanalytics.com/2012/09/how-to-use-your-favorite-fonts-in-r-charts.html
#See this link for help on fonts.
library(XML)
library(colorspace)
#library(twitteR) If you want to tweet out your plot!
library(httr)

#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){
  Sys.sleep(0.1)

  link        <- paste("http://w1.weather.gov/data/obhistory/", 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",
                            "precip3")

  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.

fl.map    <- 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                  <- mba.surf(xyz, 150, 150, extend = TRUE,
                                    sp = TRUE, b.box = mba.bbox)$xyz.est  #The 150,150 is the resolution. Make smaller to speed up processing time.

surf.w@data             <- surf.w@data * (!is.na(overlay(surf.w, 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")

dev.off()

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!

    Chris

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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 WordPress.com.

Up ↑

%d bloggers like this: