Средние значения различной длины в R - PullRequest
1 голос
/ 04 марта 2020

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

Subject  Event   R1  R2 R3 R4   Average
1        A       1   2  2  N/A   2.5
1        B       1   1  1  1     1

Таким образом, чтобы получить среднее значение для события A, было бы (R1 + R2 + R3) / 3 игнорируя N / A, тогда как событие B имеет 4 ответа. Я вычислил среднее значение для события A в dplyr следующим образом:

data$average <- data%>%filter(Event == "A") %>% with(data, (R1 + R2 + R3)/4) 

Я столкнулся с проблемами, когда попытался сделать то же самое для следующего события ... Спасибо за помощь!

Ответы [ 4 ]

3 голосов
/ 04 марта 2020

Следующее не включает значение NA как часть вычисления среднего значения ( na.rm = TRUE ). Кроме того, я думаю, что группировка по событиям важна. При запуске без group_by в вычислениях объединяются все события, и результирующее значение равно 1,285714 (= 9/7 obs).

data <- data.frame(
  Subject=c(1,1),
  Event=c('A', 'B'),
  R1=c(1,1),
  R2=c(2,1),
  R3=c(2,1),
  R4=c(NA,1)
)

df <- data %>%
  group_by(Event) %>%
  mutate(Average = mean(c(R1,R2,R3,R4), na.rm=TRUE))

Выход:

Subject Event    R1    R2    R3    R4 Average
    <dbl> <fct> <dbl> <dbl> <dbl> <dbl>   <dbl>
1       1 A         1     2     2    NA    1.67
2       1 B         1     1     1     1    1   
2 голосов
/ 04 марта 2020

Вам не нужно фильтровать каждое событие за раз. dplyr способен обрабатывать все строки одновременно, одну за другой. Также при использовании dplyr вам не нужно присваивать переменную вне контекста, например, data$average <- (something). Вы можете использовать mutate(). Таким образом, интуитивно понятный синтаксис для dplyr будет:

data <-
  data %>%
  mutate(average = mean(c(R1, R2, R3, R4), na.rm = TRUE))
1 голос
/ 04 марта 2020

Вы можете использовать rowMeans, чтобы вычислить средние значения для каждой строки кадра данных. Укажите во входных данных, какие столбцы вы хотите включить. Чтобы игнорировать NA set na.rm=TRUE.

data$Average <- rowMeans(data[,c("R1", "R2", "R3", "R4")], na.rm=TRUE)

Если у вас было много столбцов для усреднения и вы не хотите их выводить все, вы можете использовать grep, чтобы соответствовать именам data к любому шаблону. Например, вы хотите усреднить все строки, содержащие в своем имени букву «R»:

data$Average <- rowMeans(data[,grep("R",names(data))], na.rm=TRUE)
0 голосов
/ 04 марта 2020

Просто чтобы завершить все предыдущие ответы, если у вас есть несколько значений с именами R1, R2, .... R100, вместо записи всех их в функцию mean, вас может заинтересовать преобразовать ваш фрейм данных в более длинный формат с помощью функции pivot_longer, а затем сгруппировать по событию и вычислить среднее значение. Наконец, используя pivot_wider, вы можете перевести ваш фрейм данных в исходный более широкий формат.

library(dplyr)
library(tidyr)
df %>% mutate_at(vars(contains("R")), as.numeric) %>%
    pivot_longer(cols = starts_with("R"), names_to = "R", values_to = "Values") %>%
    group_by(Event) %>%
    mutate(average = mean(Values, na.rm = TRUE)) %>%
    pivot_wider(names_from = R, values_from = Values)

# A tibble: 2 x 8
# Groups:   Event [2]
  Subject Event Average average    R1    R2    R3    R4
    <int> <chr>   <dbl>   <dbl> <dbl> <dbl> <dbl> <dbl>
1       1 A         2.5    1.67     1     2     2    NA
2       1 B         1      1        1     1     1     1

Как уже упоминалось @TTS, в вычислении среднего значения события A что-то не так.

Воспроизводимый пример

structure(list(Subject = c(1L, 1L), Event = c("A", "B"), R1 = c(1L, 
1L), R2 = 2:1, R3 = 2:1, R4 = c("N/A", "1"), Average = c(2.5, 
1)), row.names = c(NA, -2L), class = c("data.table", "data.frame"
), .internal.selfref = <pointer: 0x5555743c1310>)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...