WebDev4R: The Ultimate Guide To Get Data Through APIs With {httr2} and R

WebDev
The {httr2} package is an incredible package that gives you an excellent workflow to get data via Web APIs.
Author

Albert Rapp

Published

March 3, 2024

Today, we’re talking about something that has been a mystery to me for quite some time. We are talking about APIs and how to get data from them using R. And we will do that with the help of the {httr2} package. This is quite a broad topic so this will be quite a long ride. Here’s our playbook for today:

So that’s our gameplay for this blog post. As I’ve said, this one will be a long one. Hence the name “Ultimate Guide”. But if you want to lean back and enjoy all of this content in video form, I’ve got you covered. You can find the video version of this blog post on my YouTube channel:

Level 1: Getting to know APIs

Alright, Level 1 is doing small steps with APIs. Let’s dive in.

What is an API?

API stands for Application Programming Interface. Broadly speaking, an API is anything that we can throw code at to get results that we want. Often, this refers to some data source that we tap into. But sometimes it also simply means the syntax of code. For example, ggplot2 has a very distinctive API, i.e. a code syntax to create a chart. In this blog post, though, we will just refer to APIs as data sources.

Making requests to an API

If you’ve never worked with APIs, you know that it can feel like data is hidden away behind an API. Thankfully, the {httr2} package helps us a lot, even if we’ve never dealt with APIs before. This package allows us to use a step-by-step workflow that is always the same. Here’s how it looks and don’t worry if this doesn’t mean a thing to you yet:

1️⃣ Stick a base URL it into request().

2️⃣ Pipe that request into all kinds of req_*() functions to fill your request with the parameters and authentication your request needs.

3️⃣ Perform your request after your filled in all the parameters you need with req_perform().

4️⃣ Extract the data from the response via resp_body_json() to turn the JSON response into a list.

So these are the steps that make up an API request to get data. And the cool thing is: With the US National Weather Service we can do that manually first to understand what’s going on. Just head to the following url using your web browser:

https://api.weather.gov/points/38.8894,-77.0352

If you navigate there, you will get cryptic data like that:

This is what is known as a JSON file. More on that later. For now, notice that what you see at the end of the url after points/ corresponds to the coordinates that are given in the JSON output. (Compare that with the things the red arrow is pointing at)

This means that the recipe for calling the weather API is simple: Append points/{lat},{long} at the end of the base_url, i.e. https://api.weather.gov/. In this case, {lat},{long} corresponds to the latitude and longitude of the location you want to get weather forecasts for.

Making a request with {httr2}

The {httr2} syntax to make this work mimics this quite well. Here’s how it looks.

library(httr2)
NWS_base_url <- 'https://api.weather.gov'
request(NWS_base_url) |> 
  req_url_path_append(
    'points',
    '38.8894,-77.0352'
  ) 
## <httr2_request>
## GET https://api.weather.gov/points/38.8894,-77.0352
## Body: empty

Basically, at the core of every request is the request() function that needs to know the base_url. This returns an <httr2_request> object that can be passed to further req_*() functions to modify the request.

Here, we used req_url_path_append() to modify the request but there are also other functions. We’ll learn a couple more soon enough. Finally, to actually make the request, you can pass everything to req_perform().

library(httr2)
NWS_base_url <- 'https://api.weather.gov'
NWS_response <- request(NWS_base_url) |> 
  req_url_path_append(
    'points',
    '38.8894,-77.0352'
  ) |> 
  req_perform()
NWS_response
## <httr2_response>
## GET https://api.weather.gov/points/38.8894,-77.0352
## Status: 200 OK
## Content-Type: application/geo+json
## Body: In memory (3091 bytes)

Understanding the response

As you’ve just seen, your request will return a <httr2_response> and if everything went well, the output will also show you Status: 200 OK. You can get the actual content (the JSON that you’ve seen in your web browser earlier) via one of the many resp_*() functions that handle responses. This will give you a highly nested list (which is why the output looks so huge.)

NWS_response |> 
  resp_body_json()
## $`@context`
## $`@context`[[1]]
## [1] "https://geojson.org/geojson-ld/geojson-context.jsonld"
## 
## $`@context`[[2]]
## $`@context`[[2]]$`@version`
## [1] "1.1"
## 
## $`@context`[[2]]$wx
## [1] "https://api.weather.gov/ontology#"
## 
## $`@context`[[2]]$s
## [1] "https://schema.org/"
## 
## $`@context`[[2]]$geo
## [1] "http://www.opengis.net/ont/geosparql#"
## 
## $`@context`[[2]]$unit
## [1] "http://codes.wmo.int/common/unit/"
## 
## $`@context`[[2]]$`@vocab`
## [1] "https://api.weather.gov/ontology#"
## 
## $`@context`[[2]]$geometry
## $`@context`[[2]]$geometry$`@id`
## [1] "s:GeoCoordinates"
## 
## $`@context`[[2]]$geometry$`@type`
## [1] "geo:wktLiteral"
## 
## 
## $`@context`[[2]]$city
## [1] "s:addressLocality"
## 
## $`@context`[[2]]$state
## [1] "s:addressRegion"
## 
## $`@context`[[2]]$distance
## $`@context`[[2]]$distance$`@id`
## [1] "s:Distance"
## 
## $`@context`[[2]]$distance$`@type`
## [1] "s:QuantitativeValue"
## 
## 
## $`@context`[[2]]$bearing
## $`@context`[[2]]$bearing$`@type`
## [1] "s:QuantitativeValue"
## 
## 
## $`@context`[[2]]$value
## $`@context`[[2]]$value$`@id`
## [1] "s:value"
## 
## 
## $`@context`[[2]]$unitCode
## $`@context`[[2]]$unitCode$`@id`
## [1] "s:unitCode"
## 
## $`@context`[[2]]$unitCode$`@type`
## [1] "@id"
## 
## 
## $`@context`[[2]]$forecastOffice
## $`@context`[[2]]$forecastOffice$`@type`
## [1] "@id"
## 
## 
## $`@context`[[2]]$forecastGridData
## $`@context`[[2]]$forecastGridData$`@type`
## [1] "@id"
## 
## 
## $`@context`[[2]]$publicZone
## $`@context`[[2]]$publicZone$`@type`
## [1] "@id"
## 
## 
## $`@context`[[2]]$county
## $`@context`[[2]]$county$`@type`
## [1] "@id"
## 
## 
## 
## 
## $id
## [1] "https://api.weather.gov/points/38.8894,-77.0352"
## 
## $type
## [1] "Feature"
## 
## $geometry
## $geometry$type
## [1] "Point"
## 
## $geometry$coordinates
## $geometry$coordinates[[1]]
## [1] -77.0352
## 
## $geometry$coordinates[[2]]
## [1] 38.8894
## 
## 
## 
## $properties
## $properties$`@id`
## [1] "https://api.weather.gov/points/38.8894,-77.0352"
## 
## $properties$`@type`
## [1] "wx:Point"
## 
## $properties$cwa
## [1] "LWX"
## 
## $properties$forecastOffice
## [1] "https://api.weather.gov/offices/LWX"
## 
## $properties$gridId
## [1] "LWX"
## 
## $properties$gridX
## [1] 97
## 
## $properties$gridY
## [1] 71
## 
## $properties$forecast
## [1] "https://api.weather.gov/gridpoints/LWX/97,71/forecast"
## 
## $properties$forecastHourly
## [1] "https://api.weather.gov/gridpoints/LWX/97,71/forecast/hourly"
## 
## $properties$forecastGridData
## [1] "https://api.weather.gov/gridpoints/LWX/97,71"
## 
## $properties$observationStations
## [1] "https://api.weather.gov/gridpoints/LWX/97,71/stations"
## 
## $properties$relativeLocation
## $properties$relativeLocation$type
## [1] "Feature"
## 
## $properties$relativeLocation$geometry
## $properties$relativeLocation$geometry$type
## [1] "Point"
## 
## $properties$relativeLocation$geometry$coordinates
## $properties$relativeLocation$geometry$coordinates[[1]]
## [1] -77.01723
## 
## $properties$relativeLocation$geometry$coordinates[[2]]
## [1] 38.9041
## 
## 
## 
## $properties$relativeLocation$properties
## $properties$relativeLocation$properties$city
## [1] "Washington"
## 
## $properties$relativeLocation$properties$state
## [1] "DC"
## 
## $properties$relativeLocation$properties$distance
## $properties$relativeLocation$properties$distance$unitCode
## [1] "wmoUnit:m"
## 
## $properties$relativeLocation$properties$distance$value
## [1] 2256.463
## 
## 
## $properties$relativeLocation$properties$bearing
## $properties$relativeLocation$properties$bearing$unitCode
## [1] "wmoUnit:degree_(angle)"
## 
## $properties$relativeLocation$properties$bearing$value
## [1] 223
## 
## 
## 
## 
## $properties$forecastZone
## [1] "https://api.weather.gov/zones/forecast/DCZ001"
## 
## $properties$county
## [1] "https://api.weather.gov/zones/county/DCC001"
## 
## $properties$fireWeatherZone
## [1] "https://api.weather.gov/zones/fire/DCZ001"
## 
## $properties$timeZone
## [1] "America/New_York"
## 
## $properties$radarStation
## [1] "KLWX"

Working with the response

To make sense of this highly nested list, we use glimpse() to understand the structure of the object.

library(tidyverse)
NWS_response |> 
  resp_body_json() |> 
  glimpse()
## List of 5
##  $ @context  :List of 2
##   ..$ : chr "https://geojson.org/geojson-ld/geojson-context.jsonld"
##   ..$ :List of 17
##   .. ..$ @version        : chr "1.1"
##   .. ..$ wx              : chr "https://api.weather.gov/ontology#"
##   .. ..$ s               : chr "https://schema.org/"
##   .. ..$ geo             : chr "http://www.opengis.net/ont/geosparql#"
##   .. ..$ unit            : chr "http://codes.wmo.int/common/unit/"
##   .. ..$ @vocab          : chr "https://api.weather.gov/ontology#"
##   .. ..$ geometry        :List of 2
##   .. ..$ city            : chr "s:addressLocality"
##   .. ..$ state           : chr "s:addressRegion"
##   .. ..$ distance        :List of 2
##   .. ..$ bearing         :List of 1
##   .. ..$ value           :List of 1
##   .. ..$ unitCode        :List of 2
##   .. ..$ forecastOffice  :List of 1
##   .. ..$ forecastGridData:List of 1
##   .. ..$ publicZone      :List of 1
##   .. ..$ county          :List of 1
##  $ id        : chr "https://api.weather.gov/points/38.8894,-77.0352"
##  $ type      : chr "Feature"
##  $ geometry  :List of 2
##   ..$ type       : chr "Point"
##   ..$ coordinates:List of 2
##   .. ..$ : num -77
##   .. ..$ : num 38.9
##  $ properties:List of 17
##   ..$ @id                : chr "https://api.weather.gov/points/38.8894,-77.0352"
##   ..$ @type              : chr "wx:Point"
##   ..$ cwa                : chr "LWX"
##   ..$ forecastOffice     : chr "https://api.weather.gov/offices/LWX"
##   ..$ gridId             : chr "LWX"
##   ..$ gridX              : int 97
##   ..$ gridY              : int 71
##   ..$ forecast           : chr "https://api.weather.gov/gridpoints/LWX/97,71/forecast"
##   ..$ forecastHourly     : chr "https://api.weather.gov/gridpoints/LWX/97,71/forecast/hourly"
##   ..$ forecastGridData   : chr "https://api.weather.gov/gridpoints/LWX/97,71"
##   ..$ observationStations: chr "https://api.weather.gov/gridpoints/LWX/97,71/stations"
##   ..$ relativeLocation   :List of 3
##   .. ..$ type      : chr "Feature"
##   .. ..$ geometry  :List of 2
##   .. ..$ properties:List of 4
##   ..$ forecastZone       : chr "https://api.weather.gov/zones/forecast/DCZ001"
##   ..$ county             : chr "https://api.weather.gov/zones/county/DCC001"
##   ..$ fireWeatherZone    : chr "https://api.weather.gov/zones/fire/DCZ001"
##   ..$ timeZone           : chr "America/New_York"
##   ..$ radarStation       : chr "KLWX"

And with pluck() you can easily drill down into specific parts of the list. For example, this could be used to get the URL for the hourly forecasts.

forecast_url <- NWS_response |> 
  resp_body_json() |> 
  pluck('properties', 'forecastHourly')
forecast_url
## [1] "https://api.weather.gov/gridpoints/LWX/97,71/forecast/hourly"

Repeat process for forecasts

With the new forecast URL, we can get new JSON data about the forecasts for our location.

forecast_response <- request(forecast_url) |> 
  req_perform()
forecast_response |> 
  resp_body_json() |> 
  glimpse()
## List of 4
##  $ @context  :List of 2
##   ..$ : chr "https://geojson.org/geojson-ld/geojson-context.jsonld"
##   ..$ :List of 5
##   .. ..$ @version: chr "1.1"
##   .. ..$ wx      : chr "https://api.weather.gov/ontology#"
##   .. ..$ geo     : chr "http://www.opengis.net/ont/geosparql#"
##   .. ..$ unit    : chr "http://codes.wmo.int/common/unit/"
##   .. ..$ @vocab  : chr "https://api.weather.gov/ontology#"
##  $ type      : chr "Feature"
##  $ geometry  :List of 2
##   ..$ type       : chr "Polygon"
##   ..$ coordinates:List of 1
##   .. ..$ :List of 5
##  $ properties:List of 8
##   ..$ updated          : chr "2024-03-03T11:29:50+00:00"
##   ..$ units            : chr "us"
##   ..$ forecastGenerator: chr "HourlyForecastGenerator"
##   ..$ generatedAt      : chr "2024-03-03T13:12:53+00:00"
##   ..$ updateTime       : chr "2024-03-03T11:29:50+00:00"
##   ..$ validTimes       : chr "2024-03-03T05:00:00+00:00/P7DT20H"
##   ..$ elevation        :List of 2
##   .. ..$ unitCode: chr "wmoUnit:m"
##   .. ..$ value   : num 6.1
##   ..$ periods          :List of 156
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. ..$ :List of 16
##   .. .. [list output truncated]

In that output, we can see that there is a list called periods inside of the properties list. This periods lists contains more lists which always have 16 entries. This might be where our forecast data lives.

forecast_response |> 
  resp_body_json() |> 
  pluck('properties', 'periods') |> 
  glimpse()
## List of 156
##  $ :List of 16
##   ..$ number                    : int 1
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-03T08:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-03T09:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 46
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 1
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 5.56
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 86
##   ..$ windSpeed                 : chr "2 mph"
##   ..$ windDirection             : chr "NW"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/bkn,1?size=small"
##   ..$ shortForecast             : chr "Partly Sunny"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 2
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-03T09:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-03T10:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 49
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 1
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 6.67
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 83
##   ..$ windSpeed                 : chr "2 mph"
##   ..$ windDirection             : chr "NW"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/bkn,1?size=small"
##   ..$ shortForecast             : chr "Partly Sunny"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 3
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-03T10:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-03T11:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 52
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 1
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 7.22
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 77
##   ..$ windSpeed                 : chr "2 mph"
##   ..$ windDirection             : chr "NW"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/sct,1?size=small"
##   ..$ shortForecast             : chr "Mostly Sunny"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 4
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-03T11:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-03T12:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 55
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 1
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 7.78
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 72
##   ..$ windSpeed                 : chr "2 mph"
##   ..$ windDirection             : chr "NW"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/sct,1?size=small"
##   ..$ shortForecast             : chr "Mostly Sunny"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 5
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-03T12:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-03T13:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 58
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 1
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 7.78
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 64
##   ..$ windSpeed                 : chr "2 mph"
##   ..$ windDirection             : chr "W"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/sct,1?size=small"
##   ..$ shortForecast             : chr "Mostly Sunny"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 6
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-03T13:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-03T14:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 61
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 0
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.33
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 60
##   ..$ windSpeed                 : chr "2 mph"
##   ..$ windDirection             : chr "SW"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/sct,0?size=small"
##   ..$ shortForecast             : chr "Mostly Sunny"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 7
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-03T14:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-03T15:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 62
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 0
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 7.78
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 56
##   ..$ windSpeed                 : chr "3 mph"
##   ..$ windDirection             : chr "SW"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/sct,0?size=small"
##   ..$ shortForecast             : chr "Mostly Sunny"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 8
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-03T15:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-03T16:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 62
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 0
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.33
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 58
##   ..$ windSpeed                 : chr "3 mph"
##   ..$ windDirection             : chr "SW"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/sct,0?size=small"
##   ..$ shortForecast             : chr "Mostly Sunny"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 9
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-03T16:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-03T17:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 61
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 0
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.89
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 62
##   ..$ windSpeed                 : chr "5 mph"
##   ..$ windDirection             : chr "SW"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/sct,0?size=small"
##   ..$ shortForecast             : chr "Mostly Sunny"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 10
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-03T17:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-03T18:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 60
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 0
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.89
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 64
##   ..$ windSpeed                 : chr "3 mph"
##   ..$ windDirection             : chr "SW"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/sct,0?size=small"
##   ..$ shortForecast             : chr "Mostly Sunny"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 11
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-03T18:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-03T19:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 57
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 0
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 75
##   ..$ windSpeed                 : chr "2 mph"
##   ..$ windDirection             : chr "S"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/sct,0?size=small"
##   ..$ shortForecast             : chr "Partly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 12
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-03T19:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-03T20:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 54
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 0
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 83
##   ..$ windSpeed                 : chr "2 mph"
##   ..$ windDirection             : chr "S"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/sct,0?size=small"
##   ..$ shortForecast             : chr "Partly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 13
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-03T20:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-03T21:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 53
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 0
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : int 10
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 89
##   ..$ windSpeed                 : chr "2 mph"
##   ..$ windDirection             : chr "S"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/sct,0?size=small"
##   ..$ shortForecast             : chr "Partly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 14
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-03T21:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-03T22:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 52
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 0
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : int 10
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 93
##   ..$ windSpeed                 : chr "1 mph"
##   ..$ windDirection             : chr "S"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/sct,0?size=small"
##   ..$ shortForecast             : chr "Partly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 15
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-03T22:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-03T23:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 51
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 0
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 93
##   ..$ windSpeed                 : chr "1 mph"
##   ..$ windDirection             : chr "S"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/bkn,0?size=small"
##   ..$ shortForecast             : chr "Mostly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 16
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-03T23:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T00:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 50
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 0
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 96
##   ..$ windSpeed                 : chr "0 mph"
##   ..$ windDirection             : chr "S"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/bkn,0?size=small"
##   ..$ shortForecast             : chr "Mostly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 17
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T00:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T01:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 49
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 0
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.89
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 96
##   ..$ windSpeed                 : chr "0 mph"
##   ..$ windDirection             : chr "S"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/bkn,0?size=small"
##   ..$ shortForecast             : chr "Mostly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 18
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T01:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T02:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 49
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 1
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.89
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 96
##   ..$ windSpeed                 : chr "2 mph"
##   ..$ windDirection             : chr "SE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/sct,1?size=small"
##   ..$ shortForecast             : chr "Partly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 19
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T02:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T03:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 49
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 1
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.89
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 96
##   ..$ windSpeed                 : chr "2 mph"
##   ..$ windDirection             : chr "SE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/sct,1?size=small"
##   ..$ shortForecast             : chr "Partly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 20
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T03:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T04:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 48
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 1
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.89
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 100
##   ..$ windSpeed                 : chr "1 mph"
##   ..$ windDirection             : chr "SE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/bkn,1?size=small"
##   ..$ shortForecast             : chr "Mostly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 21
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T04:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T05:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 48
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 1
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.89
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 100
##   ..$ windSpeed                 : chr "1 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/bkn,1?size=small"
##   ..$ shortForecast             : chr "Mostly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 22
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T05:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T06:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 47
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 1
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.33
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 100
##   ..$ windSpeed                 : chr "0 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/bkn,1?size=small"
##   ..$ shortForecast             : chr "Mostly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 23
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T06:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T07:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 47
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 1
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.33
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 100
##   ..$ windSpeed                 : chr "2 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/bkn,1?size=small"
##   ..$ shortForecast             : chr "Mostly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 24
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T07:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T08:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 48
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 4
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.33
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 96
##   ..$ windSpeed                 : chr "2 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/bkn,4?size=small"
##   ..$ shortForecast             : chr "Mostly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 25
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T08:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T09:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 50
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 4
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.89
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 93
##   ..$ windSpeed                 : chr "2 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/bkn,4?size=small"
##   ..$ shortForecast             : chr "Mostly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 26
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T09:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T10:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 52
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 4
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.89
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 86
##   ..$ windSpeed                 : chr "3 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/bkn,4?size=small"
##   ..$ shortForecast             : chr "Mostly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 27
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T10:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T11:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 55
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 4
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 80
##   ..$ windSpeed                 : chr "5 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/bkn,4?size=small"
##   ..$ shortForecast             : chr "Partly Sunny"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 28
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T11:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T12:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 58
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 4
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 72
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/bkn,4?size=small"
##   ..$ shortForecast             : chr "Partly Sunny"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 29
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T12:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T13:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 60
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 4
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 67
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "SE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/bkn,4?size=small"
##   ..$ shortForecast             : chr "Partly Sunny"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 30
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T13:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T14:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 62
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 8
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 62
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "SE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/bkn,8?size=small"
##   ..$ shortForecast             : chr "Partly Sunny"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 31
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T14:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T15:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 63
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 8
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 60
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "SE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/bkn,8?size=small"
##   ..$ shortForecast             : chr "Partly Sunny"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 32
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T15:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T16:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 64
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 8
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : int 10
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 60
##   ..$ windSpeed                 : chr "7 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/bkn,8?size=small"
##   ..$ shortForecast             : chr "Mostly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 33
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T16:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T17:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 63
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 8
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : int 10
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 62
##   ..$ windSpeed                 : chr "7 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/bkn,8?size=small"
##   ..$ shortForecast             : chr "Mostly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 34
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T17:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T18:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 62
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 8
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : int 10
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 65
##   ..$ windSpeed                 : chr "7 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/bkn,8?size=small"
##   ..$ shortForecast             : chr "Mostly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 35
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T18:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T19:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 60
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 8
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : int 10
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 69
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/bkn,8?size=small"
##   ..$ shortForecast             : chr "Mostly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 36
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T19:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T20:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 58
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 30
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : int 10
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 75
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,30?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 37
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T20:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T21:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 56
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 30
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : int 10
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 80
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,30?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 38
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T21:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T22:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 54
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 30
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 83
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,30?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 39
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T22:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-04T23:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 52
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 30
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 89
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,30?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 40
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-04T23:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T00:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 51
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 30
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 93
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,30?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 41
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T00:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T01:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 50
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 30
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.89
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 93
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,30?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 42
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T01:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T02:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 49
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 70
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.89
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 96
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "NE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,70?size=small"
##   ..$ shortForecast             : chr "Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 43
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T02:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T03:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 49
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 70
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.89
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 96
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "NE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,70?size=small"
##   ..$ shortForecast             : chr "Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 44
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T03:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T04:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 49
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 70
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.89
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 96
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "NE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,70?size=small"
##   ..$ shortForecast             : chr "Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 45
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T04:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T05:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 49
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 70
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.89
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 96
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "NE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,70?size=small"
##   ..$ shortForecast             : chr "Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 46
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T05:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T06:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 49
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 70
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.89
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 96
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "NE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,70?size=small"
##   ..$ shortForecast             : chr "Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 47
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T06:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T07:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 48
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 70
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.89
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 100
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "NE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,70?size=small"
##   ..$ shortForecast             : chr "Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 48
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T07:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T08:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 49
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 59
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.89
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 96
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "NE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,59?size=small"
##   ..$ shortForecast             : chr "Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 49
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T08:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T09:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 49
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 59
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.89
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 96
##   ..$ windSpeed                 : chr "7 mph"
##   ..$ windDirection             : chr "NE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,59?size=small"
##   ..$ shortForecast             : chr "Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 50
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T09:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T10:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 50
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 59
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 96
##   ..$ windSpeed                 : chr "8 mph"
##   ..$ windDirection             : chr "N"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,59?size=small"
##   ..$ shortForecast             : chr "Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 51
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T10:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T11:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 52
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 59
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 89
##   ..$ windSpeed                 : chr "8 mph"
##   ..$ windDirection             : chr "N"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,59?size=small"
##   ..$ shortForecast             : chr "Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 52
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T11:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T12:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 53
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 59
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : int 10
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 89
##   ..$ windSpeed                 : chr "8 mph"
##   ..$ windDirection             : chr "N"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,59?size=small"
##   ..$ shortForecast             : chr "Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 53
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T12:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T13:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 55
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 59
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : int 10
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 83
##   ..$ windSpeed                 : chr "7 mph"
##   ..$ windDirection             : chr "N"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,59?size=small"
##   ..$ shortForecast             : chr "Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 54
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T13:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T14:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 55
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 20
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 10.6
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 86
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "N"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,20?size=small"
##   ..$ shortForecast             : chr "Slight Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 55
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T14:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T15:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 56
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 20
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 10.6
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 83
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "N"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,20?size=small"
##   ..$ shortForecast             : chr "Slight Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 56
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T15:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T16:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 58
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 20
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 11.1
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 80
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "NW"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,20?size=small"
##   ..$ shortForecast             : chr "Slight Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 57
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T16:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T17:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 58
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 20
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 11.1
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 80
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "NW"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,20?size=small"
##   ..$ shortForecast             : chr "Slight Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 58
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T17:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T18:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 57
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 20
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 10.6
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 80
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "W"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,20?size=small"
##   ..$ shortForecast             : chr "Slight Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 59
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T18:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T19:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 56
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 20
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 11.1
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 86
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "S"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,20?size=small"
##   ..$ shortForecast             : chr "Slight Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 60
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T19:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T20:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 55
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 9
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 11.1
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 90
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "SE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/bkn,9?size=small"
##   ..$ shortForecast             : chr "Mostly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 61
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T20:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T21:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 54
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 9
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 11.1
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 93
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "SE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/bkn,9?size=small"
##   ..$ shortForecast             : chr "Mostly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 62
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T21:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T22:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 53
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 9
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 10.6
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 93
##   ..$ windSpeed                 : chr "5 mph"
##   ..$ windDirection             : chr "SE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/bkn,9?size=small"
##   ..$ shortForecast             : chr "Mostly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 63
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T22:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-05T23:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 52
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 9
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : int 10
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 93
##   ..$ windSpeed                 : chr "5 mph"
##   ..$ windDirection             : chr "SE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/bkn,9?size=small"
##   ..$ shortForecast             : chr "Mostly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 64
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-05T23:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T00:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 51
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 9
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : int 10
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 96
##   ..$ windSpeed                 : chr "5 mph"
##   ..$ windDirection             : chr "SE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/bkn,9?size=small"
##   ..$ shortForecast             : chr "Mostly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 65
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T00:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T01:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 51
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 9
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 93
##   ..$ windSpeed                 : chr "5 mph"
##   ..$ windDirection             : chr "SE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/bkn,9?size=small"
##   ..$ shortForecast             : chr "Mostly Cloudy"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 66
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T01:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T02:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 50
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 16
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 96
##   ..$ windSpeed                 : chr "5 mph"
##   ..$ windDirection             : chr "SE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,16?size=small"
##   ..$ shortForecast             : chr "Slight Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 67
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T02:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T03:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 50
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 16
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 96
##   ..$ windSpeed                 : chr "5 mph"
##   ..$ windDirection             : chr "SE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,16?size=small"
##   ..$ shortForecast             : chr "Slight Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 68
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T03:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T04:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 49
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 16
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 100
##   ..$ windSpeed                 : chr "3 mph"
##   ..$ windDirection             : chr "SE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,16?size=small"
##   ..$ shortForecast             : chr "Slight Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 69
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T04:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T05:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 49
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 16
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 100
##   ..$ windSpeed                 : chr "3 mph"
##   ..$ windDirection             : chr "SE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,16?size=small"
##   ..$ shortForecast             : chr "Slight Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 70
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T05:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T06:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 49
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 16
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 100
##   ..$ windSpeed                 : chr "5 mph"
##   ..$ windDirection             : chr "SE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,16?size=small"
##   ..$ shortForecast             : chr "Slight Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 71
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T06:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T07:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 49
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 16
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 100
##   ..$ windSpeed                 : chr "5 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,16?size=small"
##   ..$ shortForecast             : chr "Slight Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 72
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T07:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T08:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 50
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 41
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 96
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,41?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 73
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T08:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T09:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 51
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 41
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : int 10
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 96
##   ..$ windSpeed                 : chr "6 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,41?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 74
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T09:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T10:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 53
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 41
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 10.6
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 93
##   ..$ windSpeed                 : chr "7 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,41?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 75
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T10:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T11:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 54
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 41
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 10.6
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 90
##   ..$ windSpeed                 : chr "7 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,41?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 76
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T11:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T12:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 56
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 41
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 11.1
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 86
##   ..$ windSpeed                 : chr "8 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,41?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 77
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T12:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T13:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 57
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 41
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 11.7
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 86
##   ..$ windSpeed                 : chr "8 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,41?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 78
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T13:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T14:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 59
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 68
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 11.7
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 80
##   ..$ windSpeed                 : chr "9 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,68?size=small"
##   ..$ shortForecast             : chr "Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 79
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T14:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T15:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 59
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 68
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 12.2
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 83
##   ..$ windSpeed                 : chr "9 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,68?size=small"
##   ..$ shortForecast             : chr "Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 80
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T15:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T16:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 59
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 68
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 12.2
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 83
##   ..$ windSpeed                 : chr "10 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,68?size=small"
##   ..$ shortForecast             : chr "Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 81
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T16:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T17:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 59
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 68
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 12.2
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 83
##   ..$ windSpeed                 : chr "12 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,68?size=small"
##   ..$ shortForecast             : chr "Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 82
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T17:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T18:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 59
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 68
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 12.2
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 83
##   ..$ windSpeed                 : chr "12 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,68?size=small"
##   ..$ shortForecast             : chr "Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 83
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T18:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T19:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 58
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 68
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 12.2
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 86
##   ..$ windSpeed                 : chr "13 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,68?size=small"
##   ..$ shortForecast             : chr "Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 84
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T19:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T20:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 58
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 63
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 11.7
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 83
##   ..$ windSpeed                 : chr "13 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,63?size=small"
##   ..$ shortForecast             : chr "Light Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 85
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T20:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T21:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 57
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 63
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 11.7
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 86
##   ..$ windSpeed                 : chr "13 mph"
##   ..$ windDirection             : chr "E"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,63?size=small"
##   ..$ shortForecast             : chr "Light Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 86
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T21:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T22:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 56
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 63
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 11.1
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 86
##   ..$ windSpeed                 : chr "13 mph"
##   ..$ windDirection             : chr "NE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,63?size=small"
##   ..$ shortForecast             : chr "Light Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 87
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T22:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-06T23:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 55
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 63
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 11.1
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 90
##   ..$ windSpeed                 : chr "13 mph"
##   ..$ windDirection             : chr "NE"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,63?size=small"
##   ..$ shortForecast             : chr "Light Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 88
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-06T23:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-07T00:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 54
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 63
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 10.6
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 90
##   ..$ windSpeed                 : chr "13 mph"
##   ..$ windDirection             : chr "N"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,63?size=small"
##   ..$ shortForecast             : chr "Light Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 89
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-07T00:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-07T01:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 53
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 63
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : int 10
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 89
##   ..$ windSpeed                 : chr "13 mph"
##   ..$ windDirection             : chr "N"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,63?size=small"
##   ..$ shortForecast             : chr "Light Rain Likely"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 90
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-07T01:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-07T02:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 53
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 44
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 86
##   ..$ windSpeed                 : chr "13 mph"
##   ..$ windDirection             : chr "N"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,44?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 91
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-07T02:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-07T03:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 52
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 44
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 9.44
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 89
##   ..$ windSpeed                 : chr "13 mph"
##   ..$ windDirection             : chr "N"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,44?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 92
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-07T03:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-07T04:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 51
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 44
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.89
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 89
##   ..$ windSpeed                 : chr "13 mph"
##   ..$ windDirection             : chr "N"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,44?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 93
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-07T04:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-07T05:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 50
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 44
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 8.33
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 89
##   ..$ windSpeed                 : chr "13 mph"
##   ..$ windDirection             : chr "N"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,44?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 94
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-07T05:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-07T06:00:00-05:00"
##   ..$ isDaytime                 : logi FALSE
##   ..$ temperature               : int 49
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 44
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 7.78
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 89
##   ..$ windSpeed                 : chr "13 mph"
##   ..$ windDirection             : chr "N"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/night/rain,44?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 95
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-07T06:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-07T07:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 49
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 44
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 7.22
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 86
##   ..$ windSpeed                 : chr "13 mph"
##   ..$ windDirection             : chr "N"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,44?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 96
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-07T07:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-07T08:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 49
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 31
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 7.22
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 86
##   ..$ windSpeed                 : chr "13 mph"
##   ..$ windDirection             : chr "N"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,31?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 97
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-07T08:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-07T09:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 50
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 31
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 6.67
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 80
##   ..$ windSpeed                 : chr "14 mph"
##   ..$ windDirection             : chr "N"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,31?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 98
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-07T09:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-07T10:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 51
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 31
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 6.11
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 74
##   ..$ windSpeed                 : chr "14 mph"
##   ..$ windDirection             : chr "N"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,31?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##  $ :List of 16
##   ..$ number                    : int 99
##   ..$ name                      : chr ""
##   ..$ startTime                 : chr "2024-03-07T10:00:00-05:00"
##   ..$ endTime                   : chr "2024-03-07T11:00:00-05:00"
##   ..$ isDaytime                 : logi TRUE
##   ..$ temperature               : int 53
##   ..$ temperatureUnit           : chr "F"
##   ..$ temperatureTrend          : NULL
##   ..$ probabilityOfPrecipitation:List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 31
##   ..$ dewpoint                  :List of 2
##   .. ..$ unitCode: chr "wmoUnit:degC"
##   .. ..$ value   : num 6.11
##   ..$ relativeHumidity          :List of 2
##   .. ..$ unitCode: chr "wmoUnit:percent"
##   .. ..$ value   : int 69
##   ..$ windSpeed                 : chr "14 mph"
##   ..$ windDirection             : chr "N"
##   ..$ icon                      : chr "https://api.weather.gov/icons/land/day/rain,31?size=small"
##   ..$ shortForecast             : chr "Chance Light Rain"
##   ..$ detailedForecast          : chr ""
##   [list output truncated]

Aha! Each of those 16-entries lists seem to correspond to the forecast of one hour. Thus, to get the things like temperature, startTime, probabilityOfPrecipitation, and short_forecast into a nice tibble format, we have to iterate over all of these 16-entries lists and wrap the values we want into a tibble.

extracted_data <- forecast_response |> 
  resp_body_json() |> 
  pluck('properties', 'periods') |> 
  map_dfr( # iterates over each list and binds rows to a tibble
    \(x) {
      tibble(
        time = x |> pluck('startTime'),
        temp_F = x |> pluck('temperature'),
        rain_prob = x |> pluck('probabilityOfPrecipitation', 'value'),
        forecast = x |> pluck('shortForecast')
      )
    }
  )
extracted_data
## # A tibble: 156 × 4
##    time                      temp_F rain_prob forecast    
##    <chr>                      <int>     <int> <chr>       
##  1 2024-03-03T08:00:00-05:00     46         1 Partly Sunny
##  2 2024-03-03T09:00:00-05:00     49         1 Partly Sunny
##  3 2024-03-03T10:00:00-05:00     52         1 Mostly Sunny
##  4 2024-03-03T11:00:00-05:00     55         1 Mostly Sunny
##  5 2024-03-03T12:00:00-05:00     58         1 Mostly Sunny
##  6 2024-03-03T13:00:00-05:00     61         0 Mostly Sunny
##  7 2024-03-03T14:00:00-05:00     62         0 Mostly Sunny
##  8 2024-03-03T15:00:00-05:00     62         0 Mostly Sunny
##  9 2024-03-03T16:00:00-05:00     61         0 Mostly Sunny
## 10 2024-03-03T17:00:00-05:00     60         0 Mostly Sunny
## # ℹ 146 more rows

And once we have that data, we can transform the time column into a nice date-time object:

extracted_data |> 
  mutate(
    time = time |> ymd_hms()
  )
## # A tibble: 156 × 4
##    time                temp_F rain_prob forecast    
##    <dttm>               <int>     <int> <chr>       
##  1 2024-03-03 13:00:00     46         1 Partly Sunny
##  2 2024-03-03 14:00:00     49         1 Partly Sunny
##  3 2024-03-03 15:00:00     52         1 Mostly Sunny
##  4 2024-03-03 16:00:00     55         1 Mostly Sunny
##  5 2024-03-03 17:00:00     58         1 Mostly Sunny
##  6 2024-03-03 18:00:00     61         0 Mostly Sunny
##  7 2024-03-03 19:00:00     62         0 Mostly Sunny
##  8 2024-03-03 20:00:00     62         0 Mostly Sunny
##  9 2024-03-03 21:00:00     61         0 Mostly Sunny
## 10 2024-03-03 22:00:00     60         0 Mostly Sunny
## # ℹ 146 more rows

Nice! We have successfully hit the API of the National Weather Service. Level 1, check!

Level 2: Authenticating with API Keys

To get the weather forecast, we had to know the coordinates of the location we want to check the weather for. So this begs the question: How do we get coordinates in the first place?

This requires hitting the API of a geocoding service like the one from Google Maps. Unfortunately for us, Google requires us to make an authenticated call. Thus, calling the API becomes a bit more tricky.

Creating a Geocode API

Essentially what we want to do now is to send addresses like “1900 E Kenwood Blvd, Milwaukee, WI 53211, USA” to Google and get coordinates back. (Fun fact: this address refers to the Physics building of UW-Milwaukee where many of the math TAs have their office. At least it was like that when I was a math TA there.)

If you look at the Get Started Page of Google’s geocoding API, you will find a URL that looks like this:

https://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&key=

If you inspect this closely, you will find

  • a question mark ? followed by

  • address=,

  • some stuff that looks like the address “1600 Amphitheatre Parkway, Mountain View, CA” encoded into a URL, and

  • key=

And if you follow the link you will get an error message like this:

Authenticate!

Aha! The video game player in me has found enough evidence that tells me that we must find a key that we can fit into key=. And just like in a video game, this might entail a whole different quest first.

In this case, we will have to take a good look at the getting started guide again (get used to reading API docs to find out how to operate them 😭). This will reveal a crucial hint:

So I guess we follow the link into the Cloud Console which leads us into yet another doc page:

So we follow the big blue button and do all the steps to create a new project. Unfortunately, this will require us to also put in some billing information and we cannot get around that. Don’t worry: The geocoding service has a generous free tier and you will not actually get billed until you manually upgrade to a paid tier.

A project is nothing without an API

Nice, we’ve set up a new Google project. Inside of these projects we can use different APIs such as the geocoding API. The easiest way to enable that for our project is to follow the big blue button from the docs:

This is where we can acquire an API key for our project and for security we can enable that the geocoding API shall be the only API the key can unlock.

Once that is done, you’re on your project dashboard and you can head to the Credentials page. There, the “Show Key” link will lead you to your API key.

API Key Security

I’m not a security expert but here’s a word of caution for you: ⚠️ DO NOT SHARE YOUR API KEY WITH ANYONE. ⚠️

This includes not putting your API code into your R script or any other type of script. Why? Because you might want to put your code into a public repo on GitHub long after you have forgotten that you put your API key in a script file.

Same thing goes for the R console. You might share your console history as part of a repo by accident. Then, someone could just look up your API key in your R console history.

So what to do instead? It’s simple really. It’s called using “environment variables”. Usually, what you do is store an .env file (the dot is important) inside your project repository. (Put that file into .gitignore immediately!)

With dotenv::load_dot_env() you can then enable access to your .env file such that Sys.getenv('<Variable_name>') can access your API key. For example, if your API-key is 123, you could store API KEYS in the .env file as

GEOCODE_API_KEY=123
SOME_OTHER_KEY=34653462542

Then, Sys.getenv('GEOCODE_API_KEY') would return the API key 123. But you don’t want to execute this code directly! What you want to do instead is use that inside of functions that need the API key like this one here:

library(tidyverse)
library(httr2)
dotenv::load_dot_env()

geocode_base_url <- 'https://maps.googleapis.com/maps/api/geocode/json'
response <- request(geocode_base_url) |> 
  req_url_query(
    address = '1900 E Kenwood Blvd, Milwaukee, WI 53211, USA',
    key = Sys.getenv('GEOCODE_API_KEY')
  ) |>
  req_perform()

Using query parameters

This code uses the URL that we have seen earlier. You know, the one that was followed by a ?, address=... and key.... In this scenario, everything that comes before the ? is the base URL for our API call. And everything after the question mark is the query to the API.

As we know, this query need to have an address and a key. Luckily for us, {httr2} makes it easy to append that stuff to the URL via req_url_query(). Once the new URL is assembled, we just have to perform the request.

Getting the coordinates

Now, we can evaluate our API response just like we learned on Level 1. Here’s how it looks.

response |> 
  resp_body_json() |> 
  glimpse()
## List of 2
##  $ results:List of 1
##   ..$ :List of 5
##   .. ..$ address_components:List of 10
##   .. ..$ formatted_address : chr "Physics Bldg, 1900 E Kenwood Blvd, Milwaukee, WI 53211, USA"
##   .. ..$ geometry          :List of 4
##   .. ..$ place_id          : chr "ChIJyWzLWNIYBYgRfK6Wf4sFUjg"
##   .. ..$ types             :List of 1
##  $ status : chr "OK"

And by drilling down into the right parts with pluck() we find our desired coordinates:

response |> 
  resp_body_json() |> 
  pluck('results', 1, 'geometry', 'location')  |> 
  unlist()
##       lat       lng 
##  43.07515 -87.88608

Hooray! We can now find the coordinates for any address in the US.

Level 3: Authentication with Bearer Token in Headers

On to Level 3, my friends. On this level, we are going to call OpenAI’s API. In the API reference, you can find an example API request that uses curl. Here’s how it looks:

curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
     "model": "gpt-3.5-turbo",
     "messages": [{"role": "user", "content": "Say this is a test!"}],
     "temperature": 0.7
   }'

curl is a very popular command-line tool that can make requests to APIs. That’s why it’s common to find common curl request examples in the docs of APIs. And that’s also why the {httr2} package has a nice translate function for that. For example, here are some demos from the docs.

curl_translate("curl http://example.com -X DELETE")
## request("http://example.com") |> 
##   req_method("DELETE") |> 
##   req_perform()
curl_translate("curl http://example.com --header A:1 --header B:2")
## request("http://example.com") |> 
##   req_headers(
##     A = "1",
##     B = "2",
##   ) |> 
##   req_perform()
curl_translate("curl http://example.com --verbose")
## request("http://example.com") |> 
##   req_perform(verbosity = 1)

Build headers

Unfortunately, curl_translate() doesn’t seem to work for our example from openAI. So I guess we will have to thing about this after all. But the good hing is that the examples already give us most of what we need. You see, in the example that includes --header we can see that the function req_headers() was necessary. And since -H and --header are the same thing, we can translate the header part already.

oai_completions_url <- 'https://api.openai.com/v1/chat/completions'
request(oai_completions_url) |> 
  req_headers(
    'Content-Type' = 'application/json',
    Authorization  =  'Bearer $OPENAI_API_KEY'
  )

Build body

Next, we can see that the curl example includes data (-d) that is passed to it via JSON. The tell-tale sign was the { }. And if you go through the req_*() function you will notice that there is a function that has json in its name. That’s the one we’ll need.

request(oai_completions_url) |> 
  req_headers(
    'Content-Type' = 'application/json',
    Authorization  =  'Bearer $OPENAI_API_KEY'
  ) |> 
  req_body_json(
    data = list(
      model = "gpt-3.5-turbo",
      messages = list(
        role = 'user',
        content = "Say this is a test!"
      ),
      temperature = 0.7
    )
  )

All we have to do now is to replace $OPENAI_API_KEY with an API key. You can generate one for yourself via OpenAI’s platform. Once that is done, we can modify our code and make a request. Beware though that this will incur costs as you pay for using OpenAI’s API. And to make this more interesting, I’ve replaced “Say this is a test!” with something more on topic.

# Reload .env-file after including new key
dotenv::load_dot_env()
oai_response <- request(oai_completions_url) |> 
  req_headers(
    'Content-Type' = 'application/json',
    Authorization  =  glue::glue(
      'Bearer {Sys.getenv("OAI_HTTR_TUTORIAL")}'
    )
  ) |> 
  req_body_json(
    data = list(
      model = "gpt-3.5-turbo",
      messages = list(
        list(
          role = 'user',
          content = "What's {httr2} in the programming language R?"
        )
      ),
      temperature = 0.7
    )
  ) |> 
  req_perform()

In the response, you can see how many tokens this chat completion cost. You can find the costs per 1000 tokens on OpenAi’s Pricing page.

oai_response |> 
  resp_body_json() |> 
  glimpse()
## List of 7
##  $ id                : chr "chatcmpl-8uHP7exRm9ItVfa4kE6OgqV5rjmO1"
##  $ object            : chr "chat.completion"
##  $ created           : int 1708423961
##  $ model             : chr "gpt-3.5-turbo-0125"
##  $ choices           :List of 1
##   ..$ :List of 4
##   .. ..$ index        : int 0
##   .. ..$ message      :List of 2
##   .. ..$ logprobs     : NULL
##   .. ..$ finish_reason: chr "stop"
##  $ usage             :List of 3
##   ..$ prompt_tokens    : int 20
##   ..$ completion_tokens: int 64
##   ..$ total_tokens     : int 84
##  $ system_fingerprint: chr "fp_69829325d0"

In any case, ChatGPT’s response is hidden the nested layers of the list. Just like we learned before, we can drill down into the list via pluck().

oai_response |> 
  resp_body_json() |> 
  pluck('choices', 1, 'message', 'content') |> 
  # Display the text with linebreaks for nicer reading
  str_wrap(width = 60) |> 
  cat()
## {httr2} is a package in R that provides a set of functions
## for working with HTTP requests. It allows users to interact
## with web APIs, making it easier to retrieve data from
## websites or send data to web servers. The package is
## commonly used for web scraping, data retrieval, and working
## with online services.

Nice, that’s a decent answer. Three levels down, one more level to go.

Level 4: OAuth2.0 Authenticaton

Finally, let’s figure out how to handle OAuth2.0 authentication. This style of authenticating is everywhere on the web and it used to be a mystery to me. So on this levle we untangle the necessary steps for OAuth and get viewing stats via the YouTube API.

What the heck is OAuth2.0?

Authentication is a bit of mystery if you don’t take a deep dive into that topic. It always starts out innocent with an API key. And all of a sudden you need some sort of secret handshake here, two ounces of a virgin’s blood there, wait 1.25 full moon cycles and you’re authenticated. It’s a bit of a mess.

So with that said, let’s not make it more complicated than it needs to be. At the end of the day, OAuth is a way to authenticate a user without giving away their password.

This involves a lot of back and forth between the user, the app and the server. And the main ingredients in this procedure are:

  • An OAuth client

  • A URL with information about the scopes (permissions) needed

  • A URL to make the authentication requests to.

The latter two things are usually provided by the API docs and the first one is something you have to set up yourself.

Set up the OAuth client

In our case, we want to get viewing stats of a particular video from the YouTube API. So we need to set up an OAuth client for the YouTube API. This requires first enabling the YouTube API in the Google Cloud Console. We can use the same project from Level 2 and just enable the YouTube API.

There, we enable the additional YouTube Data API v3. Just hit the “Enable APIs and services” button and look for that API. Once you’ve enabled that API, you are required to set up the “OAuth consent screen”. You can leave most of the settings blank and just hit “Save and continue”. The only thing you need to do is to

  • set the client to “External” and

  • add your Googlemail as a test user.

Back on the YouTube Data API v3 page, you can create credentials. Make sure to create an OAuth client.

There, you will have to

  • set the application type to “Web application”,

  • add a name and

  • add the redirect URI. This one is important and we’ll come back to that later. Just put this to http://localhost:7094 for now. (You could change the number in the URL to any number you like.)

Once you’ve created the OAuth client, you will get a notification that everything was set up successfully. There, you should download the credentials as JSON. This one will contain all the information we need to set up the client with {httr2}.

Set up the OAuth client with {httr2}

Now we need to make sure that {httr2} can operate that client for us. This is done by using the oauth_client() function. We will need to provide the client ID, the token URL and the client secret. All of these information can be extracted from the JSON file you just downloaded (Open the JSON file with any text editor for that).

# Reload environment after adding ID and secret to .env
dotenv::load_dot_env('.env')
YT_oauth_client <- oauth_client(
  id = Sys.getenv('YT_OAuth_id_tutorial'),
  token_url = 'https://oauth2.googleapis.com/token',
  secret = Sys.getenv('YT_OAuth_secret_tutorial')
)

Set up the YT request

Nice, we have an OAuth client set up. Time to make a request to the YouTube API to get the stats of a YouTube video. I would use my own video for that but I want to make sure that I indeed access the public information of a YT video. That way, you can use the same code and get the same results.

So let’s use one of Ali Abdaal’s videos. We can get the video ID from the URL of the video.

video_id <- 'hXP5fUfBGQQ'

Then, to find out what parameters we can use to get the stats of a video, we need to consult the API docs. First thing they tell us is the URL we need to make the request to.

YT_data_URL <- 'https://www.googleapis.com/youtube/v3/videos'

And the other thing we need to know is the parameters we can use. Here, we will use

  • the part parameter to specify the information we want to get and

  • the id parameter to specify the video we want to get the information for.

request(YT_data_URL) |> 
  req_url_query(
    part = 'statistics',
    id = video_id
  )

Authenticate the request

Now that we have the request set up, we need to stick in the OAuth part in there. All we have to do is to pipe our current {httr2} chain into the function that handles the OAuth part.

YT_req <- request(YT_data_URL) |> 
  req_url_query(
    part = 'statistics',
    id = video_id
  ) |> 
  req_oauth_auth_code(
    client    = YT_oauth_client,
    scope     = 'https://www.googleapis.com/auth/youtube.readonly',
    auth_url  = 'https://accounts.google.com/o/oauth2/auth',
    port      = 7094
  ) |> 
  req_perform()

As you can see, we used the req_oauth_auth_code() function to authenticate the request. This function takes

  • the OAuth client we set up earlier,

  • the scope of the request (the permissions we need),

  • the URL to make the authentication requests to, and

  • the port we want to use for the authentication.

And you’re probably wondering where I got the correct values from. Here’s how I knew what to put in there:

  • Scope: Search for the word *“scopes”** inside of the API docs and you’ll get a list of all the scopes you can use.

  • Authentication URL: It’s in the docs as well but conveniently it’s also in the JSON file we downloaded.

  • Port: This is the number we used in the URI redirect when we set up the OAuth client inside of the Google Cloud Console.

In any case, this code now works. When we execute it, our browser will open and ask us to authenticate the request. Once we do that with our Google account, the code will continue to run and we will get the data from the YouTube API. Hooray!

Get the data

Now that we got the data from YT, we can access the returned data just like we learned in the previous levels.

YT_req |> 
  resp_body_json() |> 
  purrr::pluck('items', 1, 'statistics')
# $viewCount
# [1] "1439580"
# 
# $likeCount
# [1] "39190"
# 
# $favoriteCount
# [1] "0"
# 
# $commentCount
# [1] "667"

Looks like Ali got 1.4 million views and 40k likes on that video. Good for him. Make sure to like and view all of my videos so that my videos can keep up 🤣

Cache the keys

Now before I’ll let you scoot off to watch tons of my videos (I’m sure you’re motivated to do that now), I want to show you how to cache the keys. You see, {httr2} is so kind to cache the keys for you. This means you don’t have to authenticate every time you make a request.

But what if you clicked on the wrong account when your web browser opened up? That’s actually what happened to me. I thought my code was wrong as I got an “Access denied” error. But it was just that I authenticated with the wrong account. And due to the caching, I couldn’t authenticate again.

The way to solve that problem, is to specify a name under which your authentication should be cached. If you authenticated with the wrong account, just use a different name and you can authenticate again.

YT_req <- request(YT_data_URL) |> 
  req_url_query(
    part = 'statistics',
    id = video_id
  ) |> 
  req_oauth_auth_code(
    client    = YT_oauth_client,
    scope     = 'https://www.googleapis.com/auth/youtube.readonly',
    auth_url  = 'https://accounts.google.com/o/oauth2/auth',
    port      = 7094,
    cache_key = 'YT_tutorial'
  ) |> 
  req_perform()

Conclusion

Yaaaay, we made it thorugh the jungle of API requests and authentication. If you found this helpful, here are some other ways I can help you:


Stay in touch

If you enjoyed this post, then you may also like my weekly 3-minute newsletter. Every week, I share insights on data visualization, statistics and Shiny web app development. Reading time: 3 minutes or less. You can check it out via this link.

You can also support my work with a coffee