как перегруппировать, рассчитать среднее значение и сгенерировать новый фрейм данных в R? - PullRequest
2 голосов
/ 10 апреля 2020

Я новичок в R. Недавно я работаю над небольшим проектом. У меня есть набор данных, который выглядит следующим образом: (Извините за конфиденциальность, я не могу скопировать реальные данные) Поскольку в некоторых округах химические вещества измерялись несколько раз.

id county chemicalA chemicalB chemicalC
1    a       0.1        NA      NA
1    a       0.3        NA      NA
1    a       0.2        NA      NA
1    a       0.2        NA      NA
2    b       0.4        0.2     NA
2    b       0.1        NA     NA
3    c       0.05       NA      0.8
4    d       NA         NA      0.4
4    d       0.2        NA      0.5
4    d       0.3        NA      0.6

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

id county  meanA   meanB   meanC
 1    a     0.2     NA      NA
 2    b     0.25    0.2     NA
 3    c     0.05    NA      0.8
 4    d     0.25    NA      0.5

Я гуглил и пробовал такие функции, как tapply, group_by, но они не идеальны. Например, tapply может генерировать только вектор, но мне нужна матрица с идентификатором, чтобы я мог объединить их все для создания идеального фрейма данных. Я также попытался сначала установить фрейм данных на data.frame и заполнить его вычислениями, но я не могу объединить его по id. Есть ли другие методы, которые могут помочь мне создать идеальный фрейм данных? Спасибо!

Ответы [ 3 ]

2 голосов
/ 10 апреля 2020

Мы можем использовать summarise_at после группирования по 'id', 'county'

library(dplyr)
df1 %>%
   group_by(id, county) %>%
   summarise_at(vars(-group_cols()), mean, na.rm = TRUE)

Если в конкретном столбце для групповой комбинации есть только NA, это вернет NaN как мы используем na.rm = TRUE. Чтобы предотвратить это, мы можем иметь условие if/else

df1 %>%
   group_by(id, county) %>%
   summarise_at(vars(-group_cols()), ~ if(all(is.na(.)))
        NA_real_ else mean(., na.rm = TRUE))

или другой параметр mean_ из hablar

library(hablar)
df1 %>%
   group_by(id, county) %>%
   summarise_at(vars(-group_cols()), mean_)
# A tibble: 4 x 5
# Groups:   id [4]
#     id county chemicalA chemicalB chemicalC
#  <int> <chr>      <dbl>     <dbl>     <dbl>
#1     1 a           0.2       NA        NA  
#2     2 b           0.25       0.2      NA  
#3     3 c           0.05      NA         0.8
#4     4 d           0.25      NA         0.5

Или, если есть много других переменных, мы можем применить к цифрам c столбцы с summarise_if

df1 %>%
   group_by(id, county) %>%
   summarise_if(is.numeric, mean_)

Или для определенных c переменных, либо укажите имена столбцов, либо если в имени столбца есть какой-либо шаблон, то есть здесь имена столбцов начинается с «химического» * ​​1021 *

df1 %>%
   group_by(id, county) %>%
   summarise_at(vars(starts_with('chemical')), mean_)

data

df1 <- structure(list(id = c(1L, 1L, 1L, 1L, 2L, 2L, 3L, 4L, 4L, 4L), 
    county = c("a", "a", "a", "a", "b", "b", "c", "d", "d", "d"
    ), chemicalA = c(0.1, 0.3, 0.2, 0.2, 0.4, 0.1, 0.05, NA, 
    0.2, 0.3), chemicalB = c(NA, NA, NA, NA, 0.2, NA, NA, NA, 
    NA, NA), chemicalC = c(NA, NA, NA, NA, NA, NA, 0.8, 0.4, 
    0.5, 0.6)), class = "data.frame", row.names = c(NA, -10L))
0 голосов
/ 10 апреля 2020

В базе R, используя aggregate:

aggregate(.~id+county, df, mean, na.rm = TRUE, na.action = na.pass)

#  id county chemicalA chemicalB chemicalC
#1  1      a      0.20       NaN       NaN
#2  2      b      0.25       0.2       NaN
#3  3      c      0.05       NaN       0.8
#4  4      d      0.25       NaN       0.5

Возвращает NaN, когда нет строк для агрегации, вы можете изменить его на NA, если необходимо.

0 голосов
/ 10 апреля 2020

Используя данные встроенной диафрагмы в качестве примера, data.table позволяет группировать по by

library(data.table)
dtIris <- data.table(iris)
dtIris[, .(
  meanPL = mean(Petal.Length,  na.rm = TRUE), 
  meanPW = mean(Petal.Width, na.rm = TRUE)
), by = Species]

Или даже лучше, используя .SD, который будет принимать среднее значение для каждого столбца (не в by) или переданные .SDcols = ...

dtIris[, 
  lapply(.SD, mean, na.rm = TRUE), 
  by = Species]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...