Search for US airport weather stations w/ rnoaa

library(rnoaa)
library(crul)
library(data.table)

Airports data from https://openflights.org/data.html

airpts <- "https://raw.githubusercontent.com/jpatokal/openflights/master/data/airports.dat"
path <- "airports.csv"
invisible(crul::HttpClient$new(airpts)$get(disk = path))
airptsdf <- data.table::fread(path, data.table = FALSE)
names(airptsdf) <- c("id", "name", "city", "country",
    "iata", "icao", "latitude", "longitude", "altitude", "timezone",
    "dst", "tz_database_time_zone", "type", "source")
head(airptsdf)
  id                                        name         city          country
1  1                              Goroka Airport       Goroka Papua New Guinea
2  2                              Madang Airport       Madang Papua New Guinea
3  3                Mount Hagen Kagamuga Airport  Mount Hagen Papua New Guinea
4  4                              Nadzab Airport       Nadzab Papua New Guinea
5  5 Port Moresby Jacksons International Airport Port Moresby Papua New Guinea
6  6                 Wewak International Airport        Wewak Papua New Guinea
  iata icao  latitude longitude altitude timezone dst tz_database_time_zone
1  GKA AYGA -6.081690   145.392     5282       10   U  Pacific/Port_Moresby
2  MAG AYMD -5.207080   145.789       20       10   U  Pacific/Port_Moresby
3  HGU AYMH -5.826790   144.296     5388       10   U  Pacific/Port_Moresby
4  LAE AYNZ -6.569803   146.726      239       10   U  Pacific/Port_Moresby
5  POM AYPY -9.443380   147.220      146       10   U  Pacific/Port_Moresby
6  WWK AYWK -3.583830   143.669       19       10   U  Pacific/Port_Moresby
     type      source
1 airport OurAirports
2 airport OurAirports
3 airport OurAirports
4 airport OurAirports
5 airport OurAirports
6 airport OurAirports

limit to those in the US

airptsdf <- subset(airptsdf, country == "United States")
head(airptsdf)
       id                       name          city       country iata icao
3201 3411 Barter Island LRRS Airport Barter Island United States  BTI PABA
3202 3413 Cape Lisburne LRRS Airport Cape Lisburne United States  LUR PALU
3203 3414     Point Lay LRRS Airport     Point Lay United States  PIZ PPIZ
3204 3415 Hilo International Airport          Hilo United States  ITO PHTO
3205 3416  Orlando Executive Airport       Orlando United States  ORL KORL
3206 3417            Bettles Airport       Bettles United States  BTT PABT
     latitude longitude altitude timezone dst tz_database_time_zone    type
3201  70.1340 -143.5820        2       -9   A     America/Anchorage airport
3202  68.8751 -166.1100       16       -9   A     America/Anchorage airport
3203  69.7329 -163.0050       22       -9   A     America/Anchorage airport
3204  19.7214 -155.0480       38      -10   N      Pacific/Honolulu airport
3205  28.5455  -81.3329      113       -5   A      America/New_York airport
3206  66.9139 -151.5290      647       -9   A     America/Anchorage airport
          source
3201 OurAirports
3202 OurAirports
3203 OurAirports
3204 OurAirports
3205 OurAirports
3206 OurAirports

Search for each airport with rnoaa - using ghcnd data via meteo_* functions

ghcnd_stats <- ghcnd_stations()
# Get all stations within 2 kilometers
meteo_nearby_stations(lat_lon_df = airptsdf[1:5, ], 
    station_data = ghcnd_stats, radius = 2)
$`3411`
# A tibble: 1 x 5
  id          name                 latitude longitude distance
  <chr>       <chr>                   <dbl>     <dbl>    <dbl>
1 USW00027401 BARTER ISLAND WSO AP     70.1      -144     1.94

$`3413`
# A tibble: 2 x 5
  id          name              latitude longitude distance
  <chr>       <chr>                <dbl>     <dbl>    <dbl>
1 USC00501312 CAPE LISBURNE         68.9      -166    0.972
2 USW00026631 CAPE LISBURNE AFS     68.9      -166    1.32

$`3414`
# A tibble: 0 x 5
# ... with 5 variables: id <chr>, name <chr>, latitude <dbl>, longitude <dbl>,
#   distance <dbl>

$`3415`
# A tibble: 2 x 5
  id          name         latitude longitude distance
  <chr>       <chr>           <dbl>     <dbl>    <dbl>
1 USW00021503 HILO NAS         19.7      -155    0.563
2 USW00021504 HILO INTL AP     19.7      -155    0.587

$`3416`
# A tibble: 3 x 5
  id          name                 latitude longitude distance
  <chr>       <chr>                   <dbl>     <dbl>    <dbl>
1 USW00012841 ORLANDO EXECUTIVE AP     28.5     -81.3   0.0295
2 USW00012824 ORLANDO AAF              28.6     -81.3   0.502
3 USC00086633 ORLANDO WTP              28.6     -81.4   1.74

2 Likes

@adamhsparks talked to @maelle who may post how to do this with riem - if you have a way to do with any of your pkgs, that’d be cool to see as well

Yup, easy, a bit slow, but it gets there.

    library(GSODR)

    airpts <- "https://raw.githubusercontent.com/jpatokal/openflights/master/data/airports.dat"
    path <- "airports.csv"
    invisible(crul::HttpClient$new(airpts)$get(disk = path))
    airptsdf <- data.table::fread(path, data.table = FALSE)
    names(airptsdf) <- c("id", "name", "city", "country",
                         "iata", "icao", "latitude", "longitude", "altitude", "timezone",
                         "dst", "tz_database_time_zone", "type", "source")

    airptsdf <- subset(airptsdf, country == "United States")

    out <- vector(mode = "list", length = nrow(airptsdf))

    for (i in 1:nrow(airptsdf)) {
        j <- nearest_stations(LAT = airptsdf[i, 7], 
                                          LON = airptsdf[i, 8],
                                          distance = 2)
       out[[i]] <- c(data.frame(airptsdf[i, ]), j)
    }

The resulting list where “out[[i]][[15…n]]” are the corresponding GSODR STATIONIDs

    out[[1]]

       [[1]]
    [[1]]$id
    [1] 3411

    [[1]]$name
    [1] "Barter Island LRRS Airport"

    [[1]]$city
    [1] "Barter Island"

    [[1]]$country
    [1] "United States"

    [[1]]$iata
    [1] "BTI"

    [[1]]$icao
    [1] "PABA"

    [[1]]$latitude
    [1] 70.134

    [[1]]$longitude
    [1] -143.582

    [[1]]$altitude
    [1] 2

    [[1]]$timezone
    [1] "-9"

    [[1]]$dst
    [1] "A"

    [[1]]$tz_database_time_zone
    [1] "America/Anchorage"

    [[1]]$type
    [1] "airport"

    [[1]]$source
    [1] "OurAirports"

    [[1]][[15]]
    [1] "700860-27401"

    [[1]][[16]]
    [1] "700860-99999"

    [[1]][[17]]
    [1] "700863-99999"

    [[1]][[18]]
    [1] "700865-99999"
3 Likes

This returns just the STNIDs with the list items having the airport names.

    out <- vector(mode = "list", length = nrow(airptsdf))
    names(out) <- airptsdf$name

    for (i in 1:nrow(airptsdf)) {
        j <- nearest_stations(LAT = airptsdf[i, 7], 
                                          LON = airptsdf[i, 8],
                                          distance = 2)
       out[[i]] <-  j
    }
2 Likes

In riem there are 3 functions to get:

  • all networks (sadly 1 network per state in the US) riem_networks()
  • all weather stations for that network riem_stations()
  • measurements for a station riem_measures

Luckily all US networks are “blabla_ASOS” instead of “blabla__ASOS”. That said Canadian airports too ahah. So we should remove them as well.

all_networks <- riem::riem_networks()
us_ca_networks <- dplyr::filter(all_networks, !stringr::str_detect(code, "\\_\\_"))
us_networks <- dplyr::filter(us_ca_networks, !stringr::str_detect(code, "^CA"))
unique(us_networks$name)
#>  [1] "Alaska ASOS"         "Alabama ASOS"        "Arkansas ASOS"      
#>  [4] "Iowa AWOS"           "Arizona ASOS"        "Colorado ASOS"      
#>  [7] "Connecticut ASOS"    "Delaware ASOS"       "Florida ASOS"       
#> [10] "Georgia ASOS"        "Hawaii ASOS"         "Iowa ASOS"          
#> [13] "Idaho ASOS"          "Illinois ASOS"       "Indiana ASOS"       
#> [16] "Kansas ASOS"         "Kentucky ASOS"       "Louisiana ASOS"     
#> [19] "Massachusetts ASOS"  "Maryland ASOS"       "Maine ASOS"         
#> [22] "Michigan ASOS"       "Minnesota ASOS"      "Missouri ASOS"      
#> [25] "Mississippi ASOS"    "Montana ASOS"        "North Carolina ASOS"
#> [28] "North Dakota ASOS"   "Nebraska ASOS"       "New Hampshire ASOS" 
#> [31] "New Jersey ASOS"     "New Mexico ASOS"     "Nevada ASOS"        
#> [34] "New York ASOS"       "Ohio ASOS"           "Oklahoma ASOS"      
#> [37] "Oregon ASOS"         "Pennsylvania ASOS"   "Rhode Island ASOS"  
#> [40] "South Carolina ASOS" "South Dakota ASOS"   "Tennessee ASOS"     
#> [43] "Texas ASOS"          "Utah ASOS"           "Virginia ASOS"      
#> [46] "Vermont ASOS"        "Washington ASOS"     "Wisconsin ASOS"     
#> [49] "West Virginia ASOS"  "Wyoming ASOS"

The code below should get all stations, but I have only tested it for the two first networks. I have written a small wrapper/helper function around riem::riem_measures to keep the network name in case one wants to keep the name of the state.

get_stations_and_keep_network_name <- function(network){
  stations <- riem::riem_stations(network)
  stations$network <- network
  return(stations)
}

us_stations <- purrr::map_df(us_networks$code[1:2], get_stations_and_keep_network_name)
head(us_stations)
#> # A tibble: 6 x 5
#>   id    name                lon   lat network
#>   <chr> <chr>             <dbl> <dbl> <chr>  
#> 1 PADK  ADAK NAS/MITCHELL  -177  51.9 AK_ASOS
#> 2 PAKH  AKHIOK             -154  56.9 AK_ASOS
#> 3 PAUT  Akun               -166  54.1 AK_ASOS
#> 4 PALP  Alpine             -151  70.3 AK_ASOS
#> 5 PAFM  AMBLER             -158  67.1 AK_ASOS
#> 6 PAKP  ANAKTUVUK PASS     -152  68.1 AK_ASOS

And my take on riem:

  • Plus sides: very simple package so easier to find which functions to use, peer-reviewed, and focused on airport weather stations. Not affected by NOAA current issues.
  • Downsides: it relies on a non official data source, maintained by a very efficient person, but I’m not sure this person gets any help which makes the data source potentially fragile as well.
3 Likes