简体   繁体   中英

Apply function over data.frame values

I've been stumbling around over something I feel I should know. Given a small data.frame, say:

d <- tibble(a = c(45, 1, 2, 9), b = c(3, 19, 8, 12))

> d
# A tibble: 4 x 2
      a     b
  <dbl> <dbl>
1    45     3
2     1    19
3     2     8
4     9    12

I'd like to mutate some new variables with the result of a call to toOrdinal (from the toOrdinal library). I tried this:

d %>% mutate(
  across(everything(), ~ toOrdinal::toOrdinal(.x), .names = "ord_{col}")
)

But the results aren't right:

# A tibble: 4 x 4
      a     b ord_a ord_b
  <dbl> <dbl> <chr> <chr>
1    45     3 45th  3rd  
2     1    19 1th   19rd 
3     2     8 2th   8rd  
4     9    12 9th   12rd 

Instead, what I'd like to see is:

# A tibble: 4 x 4
      a     b ord_a ord_b
  <dbl> <dbl> <chr> <chr>
1    45     3 45th  3rd  
2     1    19 1st   19th 
3     2     8 2nd   8th  
4     9    12 9th   12th 

The warnings() , which are usually pretty helpful, aren't pointing me to what exactly I'm doing wrong.

Any guidance is appreciated!

The function is not Vectorized . Either we use rowwise or Vectorize the function

library(dplyr)
library(toOrdinal)
d %>% 
    mutate(across(everything(), ~  Vectorize(toOrdinal)(.),.names = "ord_{col}"))

-output

# A tibble: 4 x 4
#      a     b ord_a ord_b
#  <dbl> <dbl> <chr> <chr>
#1    45     3 45th  3rd  
#2     1    19 1st   19th 
#3     2     8 2nd   8th  
#4     9    12 9th   12th 

Or use rowwise

d %>%
   rowwise() %>%
   mutate(across(everything(), ~ toOrdinal(.), .names = "ord_{col}")) %>%
   ungroup

-output

# A tibble: 4 x 4
#      a     b ord_a ord_b
#  <dbl> <dbl> <chr> <chr>
#1    45     3 45th  3rd  
#2     1    19 1st   19th 
#3     2     8 2nd   8th  
#4     9    12 9th   12th 

Or another option is to do the rowwise with pmap from purrr and bind the output tibble with the original dataset

library(purrr)
library(stringr)
pmap_dfr(d, ~  map_dfr(list(...), toOrdinal)) %>% 
   rename_all(~ str_c('ord_', .)) %>%
   bind_cols(d, .)

-output

# A tibble: 4 x 4
#      a     b ord_a ord_b
#  <dbl> <dbl> <chr> <chr>
#1    45     3 45th  3rd  
#2     1    19 1st   19th 
#3     2     8 2nd   8th  
#4     9    12 9th   12th 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM