Search code examples
rfunctionweatherdarksky

How to create a function to retrieve multiple cities historical weather using R and DARKSKY api?


I'm trying to retrieve historical weather data for 100 cities in R using DARKSKY API.

The following code works to get historical data for 1 city, however I'm having issues creating a loop function to go through a list of 100 latitude and longitudes and spit out the data.

weather <- function(Long,Lat) 
{ a <-seq(Sys.Date()-10, Sys.Date(), "1 day") %>%
  map(~get_forecast_for(Long,Lat,.x, units = 'si')) %>%
  map_df('daily')

write.csv(a,"blah blah")

}

weather(52.6983,-1.0735)

My initial thought was to upload csv file with all the longitude and latitudes I require. Set them as variables and then map them to the function above.

data <- read.csv("blah blah")
Long <- data$Longitude
Lat <- data$Latitude
map(c("Long","Lat"),weather)

But it keeps bringing back error messages.

Can anyone help please?

Thank you


Solution

  • You are almost there. There are a couple of things needed to iterate the get_forecast_for function by rows. From the purrr package, the pmap function is good for repeating a function by row whereas the imap function can be used for repeating a function by cells in a row.

    Using this approach, I wrote two functions: weather_at_coords and weather. weather_at_coords is used to send a request to DarkSkyAPI for weather at specific location in a given time range (i.e., last ten days). The weather function is used to repeat the function by row.

    I saw that you wanted the nested object daily, so wrote the function to extract that list from the response. I'm assuming that you also wanted the results in a data.frame so I added bind_rows. I added a column id so that rows can be properly linked to a location (or you can add any columns that you like).

    # pkgs
    library(tidyverse)
    library(darksky)
    
    # set API Key: free from https://darksky.net/dev
    darksky::darksky_api_key()
    
    # Forecast at a given point and time period
    weather_at_coords <- function(...) {
      d <- rlang::list2(...)
      time <- seq(Sys.Date()-10, Sys.Date(), "1 day")
      response <- imap(time, ~ darksky::get_forecast_for(d$lat, d$lon, .x, units = "si")[["daily"]])
      out <- bind_rows(response) %>% mutate(id = d$id)
      return(out)
    }
    
    # primary function (iterates across rows)
    weather <- function(data) {
      result <- pmap(data, ~ weather_at_coords(...))
      return(bind_rows(result))
    }
    
    # sample data
    d <- data.frame(
      id = c("a", "b"),
      lat = c(37.8267,34.8267),
      lon = c(-122.423, -120.423)
    )
    
    # run
    x <- weather(d)
    x
    

    Notes

    1. Make sure you have the rlang package installed
    2. Adjust the lat and lon variable names as required.