Создание столбца фрейма данных R с использованием значений строк и совокупного значения

У меня есть данные об уловах рыбы. Каждая строка содержит название вида, значение улова (cpue) и некоторые другие несвязанные поля идентификации (год, местоположение, глубина и т. д.). Этот код создаст набор данных с правильной структурой:

# a sample dataset
set.seed(1337)
fish = rbind(
  data.frame(
    spp = "Flounder",
    cpue = rnorm(5, 5, 2)
  ),
  data.frame(
    spp = "Bass",
    cpue = rnorm(5, 15, 1)
  ),
  data.frame(
    spp = "Cod",
    cpue = rnorm(5, 2, 4)
  )
)

Я пытаюсь создать нормализованный столбец cpue cpue_norm. Для этого я применяю следующую функцию к каждому значению cpue:

cpue_norm = (cpue - cpue_mean)/cpue_std

Где cpue_mean и cpue_std — это, соответственно, среднее значение и стандартное отклонение cpue. Предостережение заключается в том, что мне нужно сделать это по каждому виду, т. е. когда я вычисляю cpue_norm для конкретной строки, мне нужно вычислить cpue_mean и cpue_std, используя cpue из только этого разновидность.

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

Я смог добиться некоторого прогресса с tapply:

calc_cpue_norm = function(l) {
  return((l - mean(l))/sd(l))
}

tapply(fish$cpue, fish$spp, calc_cpue_norm)

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

Любой, кто знает R лучше меня, может поделиться мудростью?


person Canadian_Marine    schedule 22.02.2021    source источник
comment
Вопрос закрыт как дублированный. Используйте это fish <- fish %>% dplyr::group_by(spp) %>% dplyr::mutate(cpue_norm = (cpue - mean(cpue, na.rm = TRUE)) / sd(cpue, na.rm = TRUE))   -  person Claudiu Papasteri    schedule 22.02.2021
comment
таблица данных: as.data.table(fish)[, cpue_norm := (cpue - mean(cpue))/sd(cpue), by = .(spp)]; основание R: ave(fish$cpue, fish$spp, FUN = function(z) (z-mean(z))/sd(z)); а у вас dplyr сверху.   -  person r2evans    schedule 22.02.2021
comment
Работает идеально. Спасибо!   -  person Canadian_Marine    schedule 22.02.2021