R - Ave vs Tapply. Всегда ли уникален (ave) ==? Если так, почему один из них существует? - PullRequest
0 голосов
/ 05 июля 2018

Рассмотрим следующее -

set.seed(1)
x <- runif(100)
y <- sample(c('M', 'F', 'D'), 100, TRUE)
aveResult <- ave(x = x, y, FUN = sum)
tapplyResult <- tapply(x, y, sum)
aveResult <- setNames(aveResult, y)
tapplyResult
aveResult[!duplicated(names(aveResult))]

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

Есть ли пример, когда одна из функций может делать то, что другая не может?

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

Просто добавьте еще одну опцию в данном конкретном случае: есть также by(x, y, FUN = sum).

В качестве дополнения к отличному посту @ akrun приведем краткий анализ различий в выходных данных между ave, tapply и by с учетом данных примера OP:

  1. ave(x, y, FUN = sum) заменяет x записи значениями, суммированными в группе, где каждая группа состоит из этих x значений с одним и тем же компонентом y. Возвращаемым объектом является вектор длиной length(x).

  2. tapply(x, y, sum) суммы x значения для каждой группы; возвращаемый объект - это массив, который имеет то же количество измерений, что и y с уникальными группами.

  3. by(x, y, sum) также суммирует x значения для каждой группы; возвращаемый объект - это список, который имеет такое же количество записей, что и y с уникальными группами.


Возможно, другой способ понять разницу между ave и tapply / by в контексте синтаксиса dplyr:

  1. ave соответствует выражению group_by + mutate:

    data.frame(x, y) %>% group_by(y) %>% mutate(x = sum(x)) %>% pull(x)
    
  2. tapply / by соответствует выражению group_by + summarise:

    data.frame(x, y) %>% group_by(y) %>% summarise(x = sum(x)) %>% pull(x)
    

Как совершенно справедливо подчеркнул @Onyambu, by и tapply совершенно разные; tapply работает на vector с, в то время как by может взять любой объект (обычно data.frame, matrix и т. Д.).

0 голосов
/ 05 июля 2018

ave - очень полезная функция base R, которая является быстрой и эффективной для создания новых столбцов на основе применения функции по группам (ниже приведен простой пример, который создает mean по группам столбцов с использованием ave, dplyr и data.table методы).

set.seed(24)
df1 <- data.frame(grp = sample(LETTERS, 1e6, replace = TRUE), val = rnorm(1e6))
system.time(with(df1, ave(val, grp)))
#   user  system elapsed 
#  0.070   0.004   0.073 

library(dplyr)
system.time(df1 %>%
              group_by(grp) %>%
              mutate(new = mean(val)))
#   user  system elapsed 
#  0.159   0.000   0.160 

library(data.table)
system.time(setDT(df1)[, new := mean(val), by = grp])
#  user  system elapsed 
#  0.056   0.000   0.057 

, в то время как tapply дает суммарный результат. Одним из основных преимуществ ave является то, что нам не нужно беспокоиться о порядке вывода, поскольку он всегда дает вывод в том же порядке строк. Это может измениться даже в некоторых tidyverse функциях. Вопрос о том, всегда ли sort ed unique значения ave всегда равен tapply - это зависит. Для некоторых функций мы можем получить суммарный вывод list в tapply

tapply(1:10, rep(LETTERS[1:3], c(3, 3, 4)), FUN = range)

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

ave(1:10, rep(LETTERS[1:3], c(3, 3, 4)), FUN = range)

и выдает предупреждение

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...