Как правило, для использования tapply
вы должны соблюдать следующие правила относительно его аргументов:
Первый аргумент должен быть или приведен к логическому, целому или числовому. Факторы, символы или другие типы не могут быть использованы здесь.
Второй аргумент должен быть или приведен к фактору, который может быть любым базовым типом данных с исключениями для более сложных типов. Это включает в себя несколько группировок, если использовать list()
, где tapply
затем возвращает матрицу.
- Поскольку этот аргумент принимает только факторы, его избыточно использовать с
as.factor()
, что, вероятно, tapply
уже делает под капотом.
- Третий аргумент должен быть функцией, которая возвращает атомное числовое значение для каждого ввода (т. Е. Первый аргумент), разбитого по группам (т. Е. Второму аргументу).
- Длина: Первый и второй аргументы должны иметь одинаковую длину, которая указывается, если оба они получены из фрейма данных, поскольку фреймы данных по определению являются объектом
class
типа list
, который содержит равные длина атомных векторов.
- Из-за этого правила избегайте выполнения различных операций с первым или вторым аргументом, так как это может привести к разной длины. Вместо этого либо выполните одну и ту же операцию для обоих векторов, либо еще лучше выполните операцию для всего фрейма данных перед вызовом
tapply
:
- Поскольку каждый
NA
поддерживает длину один (в отличие от NULL
), его присутствие не имеет значения в tapply
. Однако у дочерней функции могут быть проблемы с NA
, которые tapply
поднимает вверх по течению.
В частности, ваша проблема касается оригинальных типов: тип фактора Weight.g и POSIXlt
тип DateCt . Рассмотрите возможность преобразования этих типов в tapply
.
Но не приводите эти исходные типы напрямую к factor
, так как лежащие в его основе числовые значения или номер уровня фактора приведут к нежелательным результатам. Для преобразования чисел приведите сначала к character
. Для POSIXlt
приведите к Date
или character
. Ниже показано, как OP dput
первых десяти строк с другими методами группировки.
Данные (только два соответствующих столбца)
stinkpotDataDeparsed <- structure(list(Weight.g = structure(c(15L, 13L, 20L, 16L, 15L,
12L, NA, 12L, 15L, 20L, 26L), .Label = c("100", "105", "106",
"107", "110", "115", "1150", "120", "125", "126", "128", "130",
"135", "138", "140", "145", "150", "155", "159", "160", "165",
"168", "170", "175", "180", "185", "187", "190", "195", "20",
"200", "205", "210", "215", "220", "225", "230", "235", "245",
"250", "40", "45", "50", "55", "60", "65", "70", "75", "80",
"85", "90", "95", "oops!"), class = "factor"), DateCt = structure(list(
sec = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), min = c(0L, 0L,
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), hour = c(0L, 0L, 0L,
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), mday = c(20L, 30L, 8L, 29L,
23L, 26L, 12L, 17L, 29L, 13L, 4L), mon = c(8L, 8L, 10L, 10L,
5L, 5L, 6L, 6L, 6L, 5L, 5L), year = c(101L, 101L, 101L, 101L,
102L, 102L, 102L, 102L, 102L, 103L, 101L), wday = c(4L, 0L,
4L, 4L, 0L, 3L, 5L, 3L, 1L, 5L, 1L), yday = c(262L, 272L,
311L, 332L, 173L, 176L, 192L, 197L, 209L, 163L, 154L), isdst = c(0L,
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), zone = c("EST",
"EST", "EST", "EST", "EST", "EST", "EST", "EST", "EST", "EST",
"EST"), gmtoff = c(NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_)), .Names = c("sec",
"min", "hour", "mday", "mon", "year", "wday", "yday", "isdst",
"zone", "gmtoff"), class = c("POSIXlt", "POSIXt"), tzone = c("EST",
"EST", " "))), .Names = c("Weight.g", "DateCt"), row.names = 60:70, class = "data.frame")
Очистка
# REMOVE NAs FROM DATA FRAME TO RUN ON ALL COLUMNS BUT DOES NOT MATTER W/ tapply
stinkpotDataDeparsed <- stinkpotDataDeparsed[!is.na(stinkpotDataDeparsed$Weight.g),]
# CAST FACTOR TYPE TO NUMERIC
stinkpotDataDeparsed$Weight.g <- as.numeric(as.character(stinkpotDataDeparsed$Weight.g))
# CAST POISXlt TO DATE OR CHARACTER FOR FACTOR-ABILITY
stinkpotDataDeparsed$DateCt <- as.Date(stinkpotDataDeparsed$DateCt)
# stinkpotDataDeparsed$DateCt <- as.character(stinkpotDataDeparsed$DateCt)
Tapply (возвращает вектор)
with(stinkpotDataDeparsed, tapply(Weight.g, DateCt, mean))
# 2001-06-04 2001-09-20 2001-09-30 2001-11-08 2001-11-29 2002-06-23 2002-06-26 2002-07-17 2002-07-29 2003-06-13
# 185 140 135 160 145 140 130 130 140 160
Агрегат (возвращает фрейм данных)
aggregate(Weight.g ~ DateCt, data = stinkpotDataDeparsed, mean)
# DateCt Weight.g
# 1 2001-06-04 185
# 2 2001-09-20 140
# 3 2001-09-30 135
# 4 2001-11-08 160
# 5 2001-11-29 145
# 6 2002-06-23 140
# 7 2002-06-26 130
# 8 2002-07-17 130
# 9 2002-07-29 140
# 10 2003-06-13 160
Ave (возвращает вектор такой же длины, что и входной, поэтому может быть назначен столбец фрейма данных)
stinkpotDataDeparsed$Wgt.Mean <- with(stinkpotDataDeparsed, ave(Weight.g, DateCt, FUN=mean))
stinkpotDataDeparsed
# Weight.g DateCt Wgt.Mean
# 60 140 2001-09-20 140
# 61 135 2001-09-30 135
# 62 160 2001-11-08 160
# 63 145 2001-11-29 145
# 64 140 2002-06-23 140
# 65 130 2002-06-26 130
# 67 130 2002-07-17 130
# 68 140 2002-07-29 140
# 69 160 2003-06-13 160
# 70 185 2001-06-04 185
By (объектно-ориентированная оболочка для tapply
, возвращает список)
by(stinkpotDataDeparsed, stinkpotDataDeparsed$DateCt, FUN=function(sub) mean(sub$Weight.g))
# stinkpotDataDeparsed$DateCt: 2001-06-04
# [1] 185
# ------------------------------------------------------------
# stinkpotDataDeparsed$DateCt: 2001-09-20
# [1] 140
# ------------------------------------------------------------
# stinkpotDataDeparsed$DateCt: 2001-09-30
# [1] 135
# ------------------------------------------------------------
# stinkpotDataDeparsed$DateCt: 2001-11-08
# [1] 160
# ------------------------------------------------------------
# stinkpotDataDeparsed$DateCt: 2001-11-29
# [1] 145
# ------------------------------------------------------------
# stinkpotDataDeparsed$DateCt: 2002-06-23
# [1] 140
# ------------------------------------------------------------
# stinkpotDataDeparsed$DateCt: 2002-06-26
# [1] 130
# ------------------------------------------------------------
# stinkpotDataDeparsed$DateCt: 2002-07-17
# [1] 130
# ------------------------------------------------------------
# stinkpotDataDeparsed$DateCt: 2002-07-29
# [1] 140
# ------------------------------------------------------------
# stinkpotDataDeparsed$DateCt: 2003-06-13
# [1] 160
Rextester Demo