Сопоставление столбцов в аккуратном формате с помощью tidyverse

#r #tidyr #purrr

#r #tidyr #муррр

Вопрос:

Я часто использую шаблон, как показано ниже, где я храню данные в tibble столбцах списка using, применяю функции к используемым данным purrr::map , а затем использую pivot_longer для преобразования в аккуратный формат (длинный).

Есть ли более чистый / более идиоматичный способ сделать это за один шаг, без необходимости каждый раз поворачивать данные?

 library(tidyverse)

df <- tibble(n = 5:10)

df$data <- map(df$n, ~rnorm(.x))
df$mean <- map_dbl(df$data, ~mean(.x))
df$median <- map_dbl(df$data, ~median(.x))
 
 # A tibble: 6 x 4
      n data          mean  median
  <int> <list>       <dbl>   <dbl>
1     5 <dbl [5]>  -0.0239 -0.324 
2     6 <dbl [6]>  -0.396   0.0153
3     7 <dbl [7]>   0.506   0.711 
4     8 <dbl [8]>   0.463   0.537 
5     9 <dbl [9]>  -0.248  -0.555 
6    10 <dbl [10]> -0.153  -0.293 
 
 df <- pivot_longer(df, mean:median) 
 
 # A tibble: 12 x 4
       n data       name     value
   <int> <list>     <chr>    <dbl>
 1     5 <dbl [5]>  mean   -0.386 
 2     5 <dbl [5]>  median -0.407 
 3     6 <dbl [6]>  mean   -0.190 
 4     6 <dbl [6]>  median -0.451 
 5     7 <dbl [7]>  mean   -0.456 
 6     7 <dbl [7]>  median -0.0801
 7     8 <dbl [8]>  mean   -0.0408
 8     8 <dbl [8]>  median  0.0577
 9     9 <dbl [9]>  mean    0.273 
10     9 <dbl [9]>  median  0.410 
11    10 <dbl [10]> mean   -0.720 
12    10 <dbl [10]> median -1.01 
 

Ответ №1:

Я думаю, что у вас уже есть хороший подход, я бы использовал то же самое, объединив все функции в один канал () . %>%

Если вы хотите избежать pivot_longer шага, вы можете сгруппировать по каждой строке и создать две новые строки для каждой. Это возможно для dplyr версии 1.0.0 или выше.

 library(tidyverse)

df %>%
  mutate(data = map(n, rnorm), 
         group = row_number()) %>%
  group_by(group) %>%
  summarise(n = n,
            data = data,
            value = {tmp <- unlist(data);c(median(tmp), mean(tmp))},
            name = c('median', 'mean')) %>%
  ungroup %>%
  select(-group)

#      n   data        value   name  
#   <int> <list>        <dbl> <chr> 
# 1     5 <dbl [5]>   0.571   median
# 2     5 <dbl [5]>   0.343   mean  
# 3     6 <dbl [6]>   0.220   median
# 4     6 <dbl [6]>   0.0419  mean  
# 5     7 <dbl [7]>  -0.193   median
# 6     7 <dbl [7]>  -0.132   mean  
# 7     8 <dbl [8]>  -0.171   median
# 8     8 <dbl [8]>   0.00583 mean  
# 9     9 <dbl [9]>   0.952   median
#10     9 <dbl [9]>   0.471   mean  
#11    10 <dbl [10]>  0.684   median
#12    10 <dbl [10]>  0.250   mean  
 

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

1. Спасибо! Не могли бы вы объяснить эту строку: value = {tmp <- unlist(data);c(median(tmp), mean(tmp))} ?

2. data представляет собой список mean и median работает с векторными значениями. Сравните выходные mean(list(1:5)) данные и mean(unlist(list(1:5))) . Чтобы избежать unlist повторного ввода, я сохраняю его во временной переменной tmp и использую в median и mean .