0

I have to run a function against all variables in a data frame, basically change wind direction in degrees to direction names. I have written a function that works if I give it individual values but not working against whole data frame.

Here is my function:

compute_aggregate_wind_dir <- function(wind_dir)  {

                  if(wind_dir >= 0 && wind_dir <= 45) {
                     wind_dir = 'N' } else if(wind_dir > 45 && wind_dir <= 90) {
                     wind_dir = 'NE' } else if(wind_dir > 90 && wind_dir <= 135) {
                     wind_dir = 'E' } else if(wind_dir > 135 && wind_dir <= 180) {
                     wind_dir = 'SE' } else if(wind_dir > 180 && wind_dir <= 225) {
                     wind_dir = 'S' } else if(wind_dir > 225 && wind_dir <= 270) {
                     wind_dir = 'SW' } else if(wind_dir > 270 && wind_dir <= 315) {
                     wind_dir = 'W' } else {
                     wind_dir = 'NW' }

                 wind_dir                 

              }

Here is my data frame:

wind_direction <- data.frame(
                        wind_dir = c(0,51,95,229,175)
  )
 # Print the data frame.            
 print(wind_direction)

Here is how I am calling it to update the direction in data frame:

wind_direction = compute_aggregate_wind_dir(wind_dir)

Its printing only NW when I print the results.

> print(wind_direction) 
  wind_dir
1        0
2       51
3       95
4      229
5      175
> wind_direction = compute_aggregate_wind_dir(wind_dir)
> wind_direction
[1] "NW"

What I want to do the whole data frame is updated with the direction names instead of degrees after calling the function-

How to make it working ?

XCeptable
  • 1,247
  • 6
  • 25
  • 49

3 Answers3

3

As these are continuous values I would suggest using cut here and give appropriate labels

compute_aggregate_wind_dir <- function(x) {
   cut(x, breaks = c(-Inf, 45, 90, 135, 180, 225, 270, 315, Inf), 
          labels = c("N", "NE", "E", "SE", "S", "SW", "W", "NW"))
}

compute_aggregate_wind_dir(wind_direction$wind_dir)
#[1] N  NE E  SW SE

and if there are multiple columns which you want to update, you could use lapply and update the dataframe.

wind_direction[] <- lapply(wind_direction, compute_aggregate_wind_dir)
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
  • 1
    The early bird gets the worm +1. What more can I say? – Tim Biegeleisen Mar 18 '19 at 14:20
  • I used an example data frame here. The original data frame has few thousand entries and those are not continuous as it's real wind direction data. By cont, I understood that they increase in ascending order like you put in the answer. – XCeptable Mar 18 '19 at 14:33
  • 1
    @XCeptable maybe continuous is not the right word here but the idea is to divide numbers into buckets. So 1st bucket is from -Inf to 45, second from 45 to 90 and giving labels to those buckets. – Ronak Shah Mar 18 '19 at 14:40
1

The main problem with your current function is that it is using plain if else statements, which are not vectorized by default. While you could use base R's ifelse function here, which is vectorized, a better approach might be to use case_when from the dplyr library:

library(dplyr)

compute_aggregate_wind_dir <- function(wind_dir)  {
    case_when(
        wind_dir >= 0 && wind_dir <= 45 ~ 'N',
        wind_dir <= 90 ~ 'NE',
        wind_dir <= 135 ~ 'E',
        wind_dir <= 180 ~ 'SE',
        wind_dir <= 225 ~ 'S',
        wind_dir <= 270 ~ 'SW',
        wind_dir <= 315 ~ 'W',
        TRUE ~ 'NW'
    )
}
Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360
0

You can iterate over every value in your dataframe by using a for-loop.

The code for this would look like this and prints all the wind directions:

for (i in 1:nrow(wind_direction)) {
    print(compute_aggregate_wind_dir(wind_direction[i, ]))
}
JNab
  • 135
  • 10