Допустим, у меня есть data.frame следующей структуры:
fac1 fac2 fac3 val
1 Apple Fresh Red 2
2 Apple Old Red 3
3 Apple Hazard Red 1
4 Banana Fresh Yellow 4
5 Banana Old Yellow 5
6 Banana Hazard Yellow 1
7 Berry Fresh Purple 1
8 Berry Old Purple 1
9 Berry Hazard Purple 3
Я хочу суммировать val
тех строк, где fac2
равно Fresh
или Old
для каждого уровня фактора fac1
, и получить такой фрейм данных:
fac1 fac3 sum.freshold
1 Apple Red 5
2 Banana Yellow 9
3 Berry Purple 2
Более того, я хочу указать/обозначить уровни факторов при условии, что fac2
должно равняться Fresh
или Old
их символам (т. е. "Fresh"
и "Old"
), а не базовым целым числам, которые представляют эти уровни факторов (т. е. 1
и 2
).
> str(mydf$fac2)
Factor w/ 3 levels "Fresh","Hazard",..: 1 3 2 1 3 2 1 3 2
Вот пример:
mydf <- data.frame(fac1 = c(rep("Apple", 3), rep("Banana", 3), rep("Berry", 3)),
fac2 = rep(c("Fresh", "Old", "Hazard"), 3),
fac3 = c(rep("Red", 3), rep("Yellow", 3), rep("Purple", 3)),
val = c(2,3,1,4,5,1,1,1,3),
stringsAsFactors = T)
Одна моя попытка, которая не работает и не создает data.frame:
tapply(mydf$val, mydf$fac1, function(x) {x[mydf$fac2 == "Fresh"] + x[mydf$fac2 == "Old"]})
Подход с использованием aggregate
aggregate(val ~ fac1 + fac3, mydf[mydf$fac2 %in% c("Fresh", "Old"),], sum)
fac1 fac3 val
1 Berry Purple 2
2 Apple Red 5
3 Banana Yellow 9
Или, что еще лучше, напрямую с subset=
, спасибо @Onyambu
aggregate(val ~ fac1 + fac3, mydf, sum, subset = fac2 %in% c("Fresh", "Old"))
Редактирование, адресация именования и меток
Именование:
aggregate(cbind(sum.freshold=val) ~ fac1 + fac3,
mydf[mydf$fac2 %in% c("Fresh", "Old"),], sum)
fac1 fac3 sum.freshold
1 Berry Purple 2
2 Apple Red 5
3 Banana Yellow 9
Этикетки сохраняются:
library(expss)
mydf <- apply_labels(mydf, fac1 = "factor1", fac3 = "factor3")
as.list(aggregate(cbind(sum.freshold=val) ~ fac1 + fac3,
mydf[mydf$fac2 %in% c("Fresh", "Old"),], sum))
$fac1
LABEL: factor1
VALUES:
Berry, Apple, Banana
$fac3
LABEL: factor3
VALUES:
Purple, Red, Yellow
$sum.freshold
[1] 2 5 9
aggregate
имеет параметр subset
, с помощью которого вы передаете условие для подмножества данных: aggregate(val ~ fac1 + fac3, mydf, sum, subset = fac2 %in% c("Fresh", "Old"))
@Onyambu Хорошо, да, агрегат вполне настраиваемый и многофункциональный. Добавлю сюда такую возможность.
Спасибо большое, оба работают! Я проголосовал против. Однако решение Адриано Меллоса имеет два преимущества: 1) результирующую переменную можно сразу назвать как sum.freshold
и она не вызывается как исходная переменная val
, 2) если в исходном наборе данных есть метки переменных mydf
, они будут сохранены. в результирующем наборе данных. Я об этом не просил, но в некоторых случаях это может быть полезно.
Я добавил некоторую информацию об именах и метках.
Решение tidyverse::dplyr
:
library(tidyverse)
# --------------------
mydf %>%
filter(fac2 %in% c("Fresh", "Old")) %>%
summarise(
.by = c(fac1, fac3),
sum.freshold = sum(val))
Выход:
fac1 fac3 sum.freshold
1 Apple Red 5
2 Banana Yellow 9
3 Berry Purple 2
Я не уверен, что вы здесь хотите: «Я хочу указать уровни факторов по их символам, а не по целым числам на уровне факторов». Может, изменить порядок уровней? @JoschiNin