cut
is the usual function fur chopping numbers into factors, but the trick is that you need both a vector of breaks, plus the labels for each bin. First, we can grab a table of values from the web with a little scraping:
library(rvest)
library(tidyverse)
url <- 'http://snowfence.umn.edu/Components/winddirectionanddegreeswithouttable3.htm'
page <- read_html(url)
directions_raw <- page %>% html_node('td table') %>% html_table(header = TRUE)
directions <- directions_raw %>%
set_names(~tolower(sub(' Direction', '', .x))) %>%
slice(-1) %>%
separate(degree, c('degree_min', 'degree_max'), sep = '\\s+-\\s+', convert = TRUE)
directions
#> cardinal degree_min degree_max
#> 1 N 348.75 11.25
#> 2 NNE 11.25 33.75
#> 3 NE 33.75 56.25
#> 4 ENE 56.25 78.75
#> 5 E 78.75 101.25
#> 6 ESE 101.25 123.75
#> 7 SE 123.75 146.25
#> 8 SSE 146.25 168.75
#> 9 S 168.75 191.25
#> 10 SSW 191.25 213.75
#> 11 SW 213.75 236.25
#> 12 WSW 236.25 258.75
#> 13 W 258.75 281.25
#> 14 WNW 281.25 303.75
#> 15 NW 303.75 326.25
#> 16 NNW 326.25 348.75
To make cut
work properly, there's an additional complication in that north is a little bit at both the bottom and top of the range (both 0 to 11.25 and 348.75-360), so you'll have to add a bit to the ends of the breaks and labels to make it work right:
wind_dir <- data_frame(
date = structure(c(13514, 13515, 13516, 13517, 13518, 13519), class = "Date"),
SN = c(84084, 84084, 84084, 84084, 84084, 84084),
ws = c(21.3, 19.9, 19.3, 21.7, 14.4, 13.9),
wd = c(34.8, 37.8, 38.2, 15.1, 359, 355)
)
wind_dir <- wind_dir %>%
mutate(wd_cardinal = cut(
wd,
breaks = c(0, directions$degree_max, 360),
labels = c(directions$cardinal, 'N')
))
wind_dir
#> # A tibble: 6 x 5
#> date SN ws wd wd_cardinal
#> <date> <dbl> <dbl> <dbl> <fct>
#> 1 2007-01-01 84084 21.3 34.8 NE
#> 2 2007-01-02 84084 19.9 37.8 NE
#> 3 2007-01-03 84084 19.3 38.2 NE
#> 4 2007-01-04 84084 21.7 15.1 NNE
#> 5 2007-01-05 84084 14.4 359 N
#> 6 2007-01-06 84084 13.9 355 N