Вменение средств из агрегатной функции в набор данных для соответствующей переменной и группы - PullRequest
0 голосов
/ 23 мая 2019

У меня есть набор данных, который состоит из трех разных групп наблюдений. К сожалению, отсутствуют данные, поэтому я хочу использовать среднее значение для различных переменных и ввести среднее значение для соответствующей группы вместо NA.

df<-read.csv(id, test1, test2, test3, groupnumber
1, 9, 1, 3, 1
2, 8, 2, NA, 1
3, NA, 3, NA, 2
4, 1, 3, 4, 2
5, 2, 44, NA, 2
6, 4, 4, 1, 3
7, NA, NA, NA,3 )

Чтобы рассчитать результат теста, я сделал:

mean1<-aggregate(test1~groupnumber, data=df, FUN = mean)
mean2<-aggregate(test2~groupnumber, data=df, FUN = mean)
mean3<-aggregate(test3~groupnumber, data=df, FUN = mean)

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

id  test1   test2  test3  groupnumber
1    9        1      3         1
2    8        2      3         1
3    1.5      3      4         2
4    1        3      4         2 
5    2        44     4         2
6    4        4      1         3
7    4        4      1         3

Ответы [ 3 ]

1 голос
/ 23 мая 2019

Попробуйте dplyr пакет, mutate_at может изменять несколько столбцов одновременно.

library(dplyr)
df %>%
  group_by(groupnumber) %>%
  mutate_at(c("test1", "test2", "test3"), ~ ifelse(is.na(.), mean(., na.rm = 
    TRUE), .))

enter image description here

0 голосов
/ 23 мая 2019

Другие ответы, похоже, уже решают проблему, но я хотел предложить data.table решение. Спасибо @JMilner за образец данных.

library(data.table)

rm(list = ls())

df <- data.table(data.frame(
  id = c(1, 2, 3, 4, 5, 6, 7),
  test1 = c(9, 8, NA, 1, 2, 4, NA),
  test2 = c(1, 2, 3, 3, 44, 4, NA),
  test3 = c(3, NA, NA, 4, NA, 1, NA),
  groupnumber = c(1, 1, 2, 2, 2, 3, 3)
))


df[, `:=`(test1 = ifelse(is.na(test1), mean(test1, na.rm = TRUE), test1),
          test2 = ifelse(is.na(test2), mean(test2, na.rm = TRUE), test2),
          test3 = ifelse(is.na(test3), mean(test3, na.rm = TRUE), test3)),
   by = .(groupnumber)]


df

И результаты:

> df
   id test1 test2 test3 groupnumber
1:  1   9.0     1     3           1
2:  2   8.0     2     3           1
3:  3   1.5     3     4           2
4:  4   1.0     3     4           2
5:  5   2.0    44     4           2
6:  6   4.0     4     1           3
7:  7   4.0     4     1           3

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

Основной синтаксис для data.table является dt[i, j, by] и может рассматриваться как синтаксис SQL, где:

i является where

j является select

by это group by

Подробнее см. ?data.table

0 голосов
/ 23 мая 2019

Хороший пост об ограничениях и реализации среднего вменения

В СТОРОНУ: Пожалуйста, предоставьте данные в виде воспроизводимого файла data.frame, например (для ваших данных)

df <- data.frame(id=c(1,2,3,4,5,6,7),
                 test1=c(9,8,NA,1,2,4,NA),
                 test2=c(1,2,3,3,44,4,NA),
                 test3=c(3,NA,NA,4,NA,1,NA),
                 groupnumber=c(1,1,2,2,2,3,3))

Затем, используя циклы for, вы можете сделать это ... хотя это не красиво

# For 2:4 where 2,3,4 are the columns with tests 1 2 and 3
for(i in 2:4){

# then for each group number value
  for(j in unique(df$groupnumber)){

# index the positions in the data frame with group number = j and column i [row,column] format
    df[which(df$groupnumber==j) , i][is.na(df[which(df$groupnumber==j) , i])] <- mean(df[which(df$groupnumber==j), i], na.rm = TRUE)
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...