q<-"q=Cincinnati"
days<-"days=10"
aqi<-"aqi=no"
alerts<-"alerts=yes"Weather Forecasts API
Introduction
The data used for this exercise comes from the WeatherAPI.com which serves as a host server for weather API use. The data is hosted at www.weatherapi.com and requests for a API Key can also be made at this site. Once an API key is granted, the user can gather weather forecast data from a location of their choosing.
Some of the variables that are available to choose from are as follows:
Location
- City
- State
- Latitude and Longitude
Current Weather
- Condition
- Temperature
- Wind
- Precipitation
Forecast
- Condition
- Temperature
- Wind
- Precipitation
- Sunrise/Sunset Time
- Hourly Weather
Alerts
- Any National Weather Service alerts that may be active in the selected location
Weather Variables
The API allows you to make a few selections:
- Location
- Number of days you would like to forecast
- Whether or not you would like to include air quality
- Whether or not you would like to include alerts
That selection process looks like this:
API URL
When the API is completed, it’s URL looks like this:
http://api.weatherapi.com/v1/forecast.json?&key=myAPIKEY&q=Cincinnati&days=10&aqi=no&alerts=yes
Formatting Raw Data
Once the API gathers and runs your request, it creates a list in your RStudio environment that contains four additional lists.
Those lists are named: Location, Current, Forecast, and Alert. If you included air quality in your request, there will be an additional list for that information as well.
Converting lists into data frames
To convert the raw data lists into data frames that are usable, we can use the Json package in R. For this example, I just wanted to convert forecast and location information and exclude current weather.
There also were not any alerts at this particular time from the National Weather Service but while running the code prior to making this final example, there was a wind warning that could have been used.
The following code achieved the goal of converting those lists into two different data frames.
location_df<-weather_api_GET %>%
eval() %>%
fromJSON() %>%
use_series(location) %>%
bind_rows()forecast_df <- weather_api_GET %>%
eval() %>%
fromJSON() %>%
use_series(forecast) %>%
bind_rows()Interestingly, this code had to be modified a few times in order for RStudio to recognize it as data frame in the global environment. The function bind_rows() was necessary at the end of each code block in order for the output to be recognized as a data frame.
This is a portion of the raw data that is included in the forecast data frame:
| date | date_epoch | day.maxtemp_c | day.maxtemp_f | day.mintemp_c | day.mintemp_f | day.avgtemp_c | day.avgtemp_f | day.maxwind_mph | day.maxwind_kph | day.totalprecip_mm | day.totalprecip_in | day.totalsnow_cm | day.avgvis_km | day.avgvis_miles | day.avghumidity | day.daily_will_it_rain | day.daily_chance_of_rain | day.daily_will_it_snow | day.daily_chance_of_snow | day.condition.text | day.condition.icon | day.condition.code | day.uv | astro.sunrise | astro.sunset | astro.moonrise | astro.moonset | astro.moon_phase | astro.moon_illumination | astro.is_moon_up | astro.is_sun_up |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2024-03-20 | 1710892800 | 9.6 | 49.3 | 0.4 | 32.7 | 5.7 | 42.2 | 14.8 | 23.8 | 0.00 | 0.00 | 0 | 10.0 | 6 | 55 | 0 | 0 | 0 | 0 | Sunny | //cdn.weatherapi.com/weather/64x64/day/113.png | 1000 | 5 | 07:41:00 | 19:51:00 | 03:32 PM | 05:49:00 | Waxing Gibbous | 77 | 1 | 0 |
| 2024-03-21 | 1710979200 | 9.1 | 48.4 | -2.4 | 27.7 | 2.7 | 36.8 | 7.2 | 11.5 | 0.01 | 0.00 | 0 | 10.0 | 6 | 41 | 0 | 0 | 0 | 3 | Partly Cloudy | //cdn.weatherapi.com/weather/64x64/day/116.png | 1003 | 5 | 07:39:00 | 19:52:00 | 04:33 PM | 06:18:00 | Waxing Gibbous | 84 | 1 | 0 |
| 2024-03-22 | 1711065600 | 9.2 | 48.6 | 2.5 | 36.5 | 6.1 | 43.0 | 7.8 | 12.6 | 3.14 | 0.12 | 0 | 6.5 | 4 | 72 | 1 | 80 | 0 | 0 | Patchy rain nearby | //cdn.weatherapi.com/weather/64x64/day/176.png | 1063 | 1 | 07:37:00 | 19:53:00 | 05:35 PM | 06:43:00 | Waxing Gibbous | 91 | 1 | 0 |
| 2024-03-23 | 1711152000 | 8.1 | 46.6 | 1.6 | 34.9 | 5.7 | 42.3 | 15.4 | 24.8 | 0.98 | 0.04 | 0 | 8.5 | 5 | 65 | 1 | 80 | 0 | 0 | Patchy rain nearby | //cdn.weatherapi.com/weather/64x64/day/176.png | 1063 | 5 | 07:36:00 | 19:54:00 | 06:33 PM | 07:05:00 | Waxing Gibbous | 95 | 1 | 0 |
| 2024-03-24 | 1711238400 | 12.6 | 54.7 | -2.1 | 28.1 | 2.5 | 36.5 | 9.8 | 15.8 | 0.00 | 0.00 | 0 | 10.0 | 6 | 51 | 0 | 0 | 0 | 0 | Sunny | //cdn.weatherapi.com/weather/64x64/day/113.png | 1000 | 1 | 07:34:00 | 19:55:00 | 07:32 PM | 07:25:00 | Waxing Gibbous | 98 | 1 | 0 |
This is a portion of the raw data that is included in the location data frame:
| name | region | country | lat | lon | tz_id |
|---|---|---|---|---|---|
| Cincinnati | Ohio | United States of America | 39.16 | -84.46 | America/New_York |
Combining the Data Frames
In order to get one clean data frame, combining the two individual data frames is necessary. Unfortunately, it’s not a simple as a left_join() as the two data frames do not share any characteristics to join on. Additionally, the observation number is different for the two frames so just appending those columns using a function such as cbind() as it would result in an error.
To overcome this issue, the length of observations in the location data frame should be the same as the length of observations in the forecast data frame and then the cbind() can be used to combine the two data frames into a single data frame that is navigable. The code to configure this loop is as follows:
# This code will execute a command to duplicate the number
# of rows of the forecast data frame
location_df<-
location_df[rep(seq_len(nrow(location_df)),
each=nrow(forecast_df)),]To be fair, AI was utilized to create this code but the way it works is by repeating the duplication process based on the length of the forecast data frame. It works very similarly to a loop.
From there combining the data frames together was simple by using the cbind() function in R.
# Combine the two data frames by overwriting the forecast_df
forecast_df<-
cbind(location_df, forecast_df)The first few observations of the final forecast data frame looks something like this:
| name | region | country | lat | lon | tz_id | date | date_epoch | day.maxtemp_c | day.maxtemp_f | day.mintemp_c | day.mintemp_f | day.avgtemp_c | day.avgtemp_f | day.maxwind_mph | day.maxwind_kph | day.totalprecip_mm | day.totalprecip_in | day.totalsnow_cm | day.avgvis_km | day.avgvis_miles | day.avghumidity | day.daily_will_it_rain | day.daily_chance_of_rain | day.daily_will_it_snow | day.daily_chance_of_snow | day.condition.text | day.condition.icon | day.condition.code | day.uv | astro.sunrise | astro.sunset | astro.moonrise | astro.moonset | astro.moon_phase | astro.moon_illumination | astro.is_moon_up | astro.is_sun_up |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Cincinnati | Ohio | United States of America | 39.16 | -84.46 | America/New_York | 2024-03-20 | 1710892800 | 9.6 | 49.3 | 0.4 | 32.7 | 5.7 | 42.2 | 14.8 | 23.8 | 0.00 | 0.00 | 0 | 10.0 | 6 | 55 | 0 | 0 | 0 | 0 | Sunny | //cdn.weatherapi.com/weather/64x64/day/113.png | 1000 | 5 | 07:41:00 | 19:51:00 | 03:32 PM | 05:49:00 | Waxing Gibbous | 77 | 1 | 0 |
| Cincinnati | Ohio | United States of America | 39.16 | -84.46 | America/New_York | 2024-03-21 | 1710979200 | 9.1 | 48.4 | -2.4 | 27.7 | 2.7 | 36.8 | 7.2 | 11.5 | 0.01 | 0.00 | 0 | 10.0 | 6 | 41 | 0 | 0 | 0 | 3 | Partly Cloudy | //cdn.weatherapi.com/weather/64x64/day/116.png | 1003 | 5 | 07:39:00 | 19:52:00 | 04:33 PM | 06:18:00 | Waxing Gibbous | 84 | 1 | 0 |
| Cincinnati | Ohio | United States of America | 39.16 | -84.46 | America/New_York | 2024-03-22 | 1711065600 | 9.2 | 48.6 | 2.5 | 36.5 | 6.1 | 43.0 | 7.8 | 12.6 | 3.14 | 0.12 | 0 | 6.5 | 4 | 72 | 1 | 80 | 0 | 0 | Patchy rain nearby | //cdn.weatherapi.com/weather/64x64/day/176.png | 1063 | 1 | 07:37:00 | 19:53:00 | 05:35 PM | 06:43:00 | Waxing Gibbous | 91 | 1 | 0 |
| Cincinnati | Ohio | United States of America | 39.16 | -84.46 | America/New_York | 2024-03-23 | 1711152000 | 8.1 | 46.6 | 1.6 | 34.9 | 5.7 | 42.3 | 15.4 | 24.8 | 0.98 | 0.04 | 0 | 8.5 | 5 | 65 | 1 | 80 | 0 | 0 | Patchy rain nearby | //cdn.weatherapi.com/weather/64x64/day/176.png | 1063 | 5 | 07:36:00 | 19:54:00 | 06:33 PM | 07:05:00 | Waxing Gibbous | 95 | 1 | 0 |
| Cincinnati | Ohio | United States of America | 39.16 | -84.46 | America/New_York | 2024-03-24 | 1711238400 | 12.6 | 54.7 | -2.1 | 28.1 | 2.5 | 36.5 | 9.8 | 15.8 | 0.00 | 0.00 | 0 | 10.0 | 6 | 51 | 0 | 0 | 0 | 0 | Sunny | //cdn.weatherapi.com/weather/64x64/day/113.png | 1000 | 1 | 07:34:00 | 19:55:00 | 07:32 PM | 07:25:00 | Waxing Gibbous | 98 | 1 | 0 |
Theoretically, a user could use multiple API calls to many different areas and compare forecasts based on a variety of variables, such as location or how close the location is to a body of water.
Visual
A few visuals can help users see what happens in the background before they see the weather report on the local news, for instance.
To create a 7 day forecast, this R code could be used:
forecast_df %>%
head(7) %>%
### Convert date into a format that can be read by ggplot
mutate(date = ymd(date),
day = day(date),
weekday = weekdays(date),
### Must add this next line to make sure days on the xaxis are in order
weekday = gsub(" ", "", paste(day, ", ", weekday))
) %>%
### Define the aesthetics
ggplot(aes(weekday, day.maxtemp_f)
)+
### Define the type of chart
geom_col(fill = "bisque1", color = "black"
)+
### Add titles
labs(title = "7 Day Temperature Forecast",
subtitle = "In Cincinnati Ohio",
x = "",
y = ""
)+
### Tilt x-axis and remove y-axis labels
theme(axis.text.x = element_text(angle = 45, hjust = 1),
axis.text.y = element_blank()
)+
### Change y axis notation
scale_y_continuous(labels = function(x) paste(x, "°F"), limits = c(0, 80)
)+
### Add data callouts
geom_text(aes(label = paste0(round(day.maxtemp_f), "°F"), y = day.maxtemp_f),
vjust = -0.5, color = "black", size = 4
)This is an example of a neat visual that can be created using the weather API. Looks like Cincinnati shouldn’t expect it to warm up anytime soon :(.
Summary
This is a pretty cool API for pulling up to the minute weather conditions from a specific location. What I found interesting was that there was no lag delay. If I ran an API request at 11:23am, the API returned the current weather conditions at 11:23am. I would have assumed there would have been some update delay of around 15 to 20 minutes but that was not the case. You could do some cool things with this and I would assume that similar APIs are used by companies such as Windows to display the weather at the bottom of Windows operating systems on the desktop.