pmap_dbl и mean, Странные результаты

Вопрос или проблема

Когда я тестирую расчеты для каждой строки, функция суммы выдает результаты правильно, в то время как данные для функции среднего значения берутся только из первого столбца. Я не совсем понимаю причину этого……

library(tidyverse)

data <- tibble(
  x = as.numeric(1:9 *50),
  y = as.numeric(10:18),
  z = as.numeric(-10:-2)
)

data %>%
  mutate(sum = pmap_dbl(.,sum),
         mean = pmap_dbl(.,mean))
# A tibble: 9 × 5
      x     y     z   sum  mean
  <dbl> <dbl> <dbl> <dbl> <dbl>
1    50    10   -10    50    50
2   100    11    -9   102   100
3   150    12    -8   154   150
4   200    13    -7   206   200
5   250    14    -6   258   250
6   300    15    -5   310   300
7   350    16    -4   362   350
8   400    17    -3   414   400
9   450    18    -2   466   450

Может кто-то помочь объяснить эту ситуацию?

Подпись функции base::sum() – это sum(..., na.rm = FALSE), где ... – это значения для суммы. Она будет вычислять сумму всех предоставленных аргументов, если они не называются na.rm, например:

sum(1, 2) # 3
sum(2, countme = 3) # 5

С другой стороны, подпись функции для base::mean() – это mean(x, ...), где x является вектором значений, например:

mean(1,2,3) # интерпретируется как mean(x = 1, trim = 0, na.rm = FALSE, 2, 3)
# [1] 1
mean(c(1,2,3))
# [1] 1 

purrr::pmap_chr() передает аргументы отдельно. Если мы возьмем, например, вашу вторую строку, то происходит следующее:

sum(100, 11, -9)
# [1] 102

mean(100, 11, -9)
# [1] 100

Это потому, что ваш вызов функции интерпретируется как mean(100). ... предназначен для дополнительных аргументов, передаваемых в другие методы или из них, и в этом случае они игнорируются.

Что вы хотите сделать во втором случае – это следующее:

mean(c(100, 11, -9))
# [1] 34

Поскольку вы уже вычисляете сумму, вы можете использовать это для вычисления среднего, например.

data %>%
    mutate(
        sum = rowSums(.),
        mean = sum / ncol(.)
    )
# # A tibble: 9 × 5
#       x     y     z   sum  mean
#   <dbl> <dbl> <dbl> <dbl> <dbl>
# 1    50    10   -10    50  16.7
# 2   100    11    -9   102  34  
# 3   150    12    -8   154  51.3
# 4   200    13    -7   206  68.7
# 5   250    14    -6   258  86  
# 6   300    15    -5   310 103. 
# 7   350    16    -4   362 121. 
# 8   400    17    -3   414 138  
# 9   450    18    -2   466 155. 

Пока пользователь SamR объясняет причину, я предложу альтернативный вариант. Просто выполните

> transform(d0, sum = rowSums(d0), mean = rowMeans(d0))
    x  y   z sum      mean
1  50 10 -10  50  16.66667
2 100 11  -9 102  34.00000
3 150 12  -8 154  51.33333
4 200 13  -7 206  68.66667
5 250 14  -6 258  86.00000
6 300 15  -5 310 103.33333
7 350 16  -4 362 120.66667
8 400 17  -3 414 138.00000
9 450 18  -2 466 155.33333

где d0 – это ваши данные. Без дополнительных пакетов.

Ответ или решение

При анализе результатов выполнения функции pmap_dbl в вашем коде, важно понимать, как работают функции sum и mean, а также, как purrr::pmap передает аргументы в эти функции. Давайте разберем вашу задачу более подробно, чтобы прояснить ситуацию.

Проблема описания

Вы упомянули, что при вычислении суммы с помощью функции sum все работает корректно, но результаты для функции mean выглядят странными — они отображают значение только из первого столбца. Это действительно так, и причина кроется в различии в том, как эти функции обрабатывают аргументы.

Анализ поведения функций

  1. Функция sum:
    Функция sum принимает произвольное количество аргументов:

    sum(..., na.rm = FALSE)

    Она складывает все значения, переданные в аргументах, что делает ее удобной для работы с различными входными данными.

  2. Функция mean:
    Напротив, функция mean принимает вектор значений:

    mean(x, ...)

    Таким образом, если вы передадите несколько отдельных значений, как это делает pmap, mean будет интерпретировать это как mean(x = первое значение) и проигнорирует остальные. Это и объясняет, почему вы получаете значение только первого столбца.

Примеры работы функций

Рассмотрим ситуацию с конкретными данными из вашего примера:

data %>%
  mutate(sum = pmap_dbl(., sum),
         mean = pmap_dbl(., mean))

Для строки:

  • x = 100, y = 11, z = -9
  • sum(100, 11, -9) выдает 102
  • mean(100, 11, -9) интерпретируется как mean(100) и дает 100

Правильное использование

Если целью является вычисление среднего арифметического для всех столбцов, рекомендуется использовать mean как:

mean(c(x, y, z))

Однако так как вы уже вычисляете сумму, можно использовать следующий подход для нахождения среднего:

data %>%
  mutate(sum = rowSums(.),
         mean = sum / ncol(.))

Это даст вам правильные значения среднего, избегая проблем с интерпретацией аргументов.

Альтернативный подход

Вы также можете использовать функцию rowMeans, которая специально разработана для вычисления среднего по строкам матриц или таблиц:

data %>%
  mutate(sum = rowSums(.),
         mean = rowMeans(.))

Это упростит ваш код и будет более читабельно.

Заключение

Работа с pmap для различных функций требует понимания того, как именно они обрабатывают передаваемые аргументы. Разграничение этих понятий, а также использование более подходящих функций, таких как rowSums и rowMeans, поможет вам избежать подобных проблем в будущем. Используйте эти навыки и подходы для повышения эффективности вашего кода в R и облегчи работу с данными.

Оцените материал
Добавить комментарий

Капча загружается...