вычисление среднего значения путем сохранения всех переменных в наборе данных в r - PullRequest
1 голос
/ 29 января 2020

Я пытаюсь вычислить среднее время, сохраняя все переменные в конечном наборе данных в пакете dplyr. Вот как выглядит мой примерный набор данных:

library(dplyr)
id <-     c(1,1,1,1, 2,2,2,2, 3,3,3,3, 4,4,4,4)
gender <- c(1,1,1,1, 2,2,2,2, 2,2,2,2, 1,1,1,1)
item.id <-c(1,1,1,2, 1,1,2,2, 1,2,3,4, 1,2,2,3)
sequence<-c(1,2,3,1, 1,2,1,2, 1,1,1,1, 1,1,2,1)
time <-   c(5,6,7,1, 2,3,4,9, 1,2,3,9, 5,6,7,8)
data <- data.frame(id, gender, item.id, sequence, time)
> data
   id gender item.id sequence time
1   1      1       1        1    5
2   1      1       1        2    6
3   1      1       1        3    7
4   1      1       2        1    1
5   2      2       1        1    2
6   2      2       1        2    3
7   2      2       2        1    4
8   2      2       2        2    9
9   3      2       1        1    1
10  3      2       2        1    2
11  3      2       3        1    3
12  3      2       4        1    9
13  4      1       1        1    5
14  4      1       2        1    6
15  4      1       2        2    7
16  4      1       3        1    8

id для идентификатора студента, gender для пола, item.id для идентификаторов вопросов, которые принимают студенты, sequence - это порядковый номер попыток решить вопрос, потому что студенты могут вернуться к вопросам и попытаться ответить снова, а time - это время, затраченное на каждое испытание.

При вычислении среднего времени мне нужно выполнить три шага:

(a) учащиеся проходят несколько испытаний по каждому вопросу. Мне нужно рассчитать среднее время для каждого предмета, имеющего несколько испытаний.

(b), затем рассчитайте общее среднее время для каждого id. Например, для id=1 у меня есть два предмета, первый предмет имеет 3 испытания, а второй предмет - 1 испытание. Сначала мне нужно собрать время для первого элемента на (5+6+7)/3=6, поэтому id=1 имеет время элемента 1 6 и время элемента 2 1. Во-вторых, беря 6 и 1 и вычисляя среднее значение для этого ученика (6+1)/2=3.5.

(c) Наконец, я хотел бы сохранить все переменные в наборе данных.

 data <- data %>%
          group_by(id) %>%
          select(id, gender, item.id, sequence, time) %>%
          summarize(mean.time = mean(time))

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

> data
# A tibble: 4 x 2
     id mean.time
  <dbl>     <dbl>
1     1      4.75
2     2      4.5 
3     3      3.75
4     4      6.5 

Я думал, что select() собирается сохранить все переменные.

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

> data
   id gender item.id sequence time  mean.time
1   1      1       1        1    5    3.5
2   1      1       1        2    6    3.5
3   1      1       1        3    7    3.5
4   1      1       2        1    1    3.5
5   2      2       1        1    2    4.5
6   2      2       1        2    3    4.5
7   2      2       2        1    4    4.5
8   2      2       2        2    5    4.5
9   3      2       1        1    1    3.75
10  3      2       2        1    2    3.75
11  3      2       3        1    3    3.75
12  3      2       4        1    9    3.75
13  4      1       1        1    5    6.5
14  4      1       2        1    6    6.5
15  4      1       2        2    7    6.5
16  4      1       3        1    8    6.5

Я использовал dplyr, но открывал любые другие решения. Заранее спасибо!

1 Ответ

2 голосов
/ 29 января 2020

Мы можем использовать mutate вместо summarise, так как summarise возвращает суммарный вывод по 1 строке для каждой группы, тогда как mutate создает новый столбец в наборе данных

...
  %>% 
      mutate(mean.time = mean(time))

Если мы хотим получить mean из mean, то сначала группируем по 'id', 'item.id', получаем mean, а затем группируем по 'id', получаем mean из unique elements

data %>%
   group_by(id, item.id) %>% 
   mutate(mean.time = mean(time)) %>% 
   group_by(id) %>% 
   mutate(mean.time = mean(unique(mean.time)))
# A tibble: 16 x 6
# Groups:   id [4]
#      id gender item.id sequence  time mean.time
#   <dbl>  <dbl>   <dbl>    <dbl> <dbl>     <dbl>
# 1     1      1       1        1     5      3.5 
# 2     1      1       1        2     6      3.5 
# 3     1      1       1        3     7      3.5 
# 4     1      1       2        1     1      3.5 
# 5     2      2       1        1     2      4.5 
# 6     2      2       1        2     3      4.5 
# 7     2      2       2        1     4      4.5 
# 8     2      2       2        2     9      4.5 
# 9     3      2       1        1     1      3.75
#10     3      2       2        1     2      3.75
#11     3      2       3        1     3      3.75
#12     3      2       4        1     9      3.75
#13     4      1       1        1     5      6.5 
#14     4      1       2        1     6      6.5 
#15     4      1       2        2     7      6.5 
#16     4      1       3        1     8      6.5 

Или вместо того, чтобы создать вторую группу, мы можем сделать match, чтобы получить первую позицию в item.id, извлечь «mean.time» и получить mean

data %>%
   group_by(id, item.id) %>% 
   mutate(mean.time = mean(time), 
          mean.time = mean(mean.time[match(unique(item.id), item.id)]))

Или используйте summarise, а затем выполните left_join

data %>%
  group_by(id, item.id) %>%
  summarise(mean.time = mean(time)) %>%
  group_by(id) %>%
  summarise(mean.time = mean(mean.time)) %>%
  right_join(data)
...