Home > Mobile >  R handle vector values in addition to scalar values with rounding function
R handle vector values in addition to scalar values with rounding function

Time:02-13

round2 <- function(x, y) {
  if(is.na(x)) { return ('') }
  return(paste0(round(100 * x, 0), '% ', round(100 * y, 0), '%')) 
}

mydf <- data.frame(a = c(NA, .323, .555), b = c(NA, .232, .541))
mydf %>% dplyr::mutate(c = round2(a, b))

The main part of the function paste0(round(...)) works just fine, however the if(is.na(x)) { return ('') } does not properly handle that x and y are vectors. As a result, the entire column c in mydf is an empty string. How can we update this so only the first row in mydf returns an empty string?

CodePudding user response:

if/else are not vectorized - expect a single TRUE/FALSE it can work if we use rowwise as grouping

library(dplyr)
mydf %>%
   rowwise %>%
   dplyr::mutate(c = round2(a, b)) %>%
   ungroup

-output

# A tibble: 3 × 3
       a      b c        
   <dbl>  <dbl> <chr>    
1 NA     NA     ""       
2  0.323  0.232 "32% 23%"
3  0.555  0.541 "56% 54%"

as grouping or Vectorize the function

mydf %>% 
   dplyr::mutate(c = Vectorize(round2)(a, b)) 

If we want to create a vectorized function, make use of ifelse/case_when etc which are already vectorized

round2new <- function(x, y) {
    case_when(is.na(x) ~ "", 
   TRUE ~ paste0(round(100 * x, 0), '% ', round(100 * y, 0), '%'))
}
mydf %>%
   dplyr::mutate(c = round2new(a, b))
      a     b       c
1    NA    NA        
2 0.323 0.232 32% 23%
3 0.555 0.541 56% 54%

NOTE: Calling Vectorize or using rowwise grouping is iterating over each row and will be slower than making use of vectorized functions (ifelse/case_when/if_else) while constructing the function

CodePudding user response:

the if () function if you pass a vector, it will only take the first value of vector.. also a warning will be displayed on console..

better you pass the vector in function call and use the for call up to length of vector and check each x[j] j=1:length(x)

or you can use

vec [1] 2 3 NA sum(is.na(vec)) [1] 1

something like this in your logic building..

  • Related