Применить функцию к данным.значениям фрейма

#r #dplyr

#r #dplyr

Вопрос:

Я спотыкался о то, что, как мне кажется, я должен знать. Учитывая небольшой фрейм данных, скажем:

 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
 

Я хотел бы изменить некоторые новые переменные в результате вызова toOrdinal (из библиотеки toOrdinal). Я попробовал это:

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

Но результаты неверны:

 # 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 
 

Вместо этого я хотел бы видеть:

 # 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 
 

Те warnings() , которые обычно очень полезны, не указывают мне, что именно я делаю неправильно.

Любые рекомендации приветствуются!

Ответ №1:

Функция не Vectorized является . Либо мы используем rowwise , либо Vectorize функцию

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

-вывод

 # 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 
 

Или использовать rowwise

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

-вывод

 # 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 
 

Или другой вариант — выполнить последовательное с pmap помощью from purrr и связать выходной tibble с исходным набором данных

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

-вывод

 # 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 
 

Комментарии:

1. Ах, да. Спасибо! Я читал о rowwise(), но не применял его на практике. В этом есть большой смысл. Еще раз спасибо вам.