Szukałem tego od jakiegoś czasu, ale do tej pory nie udało mi się znaleźć jasnej odpowiedzi. Prawdopodobnie szukałem niewłaściwych terminów, ale może ktoś tutaj może mi szybko pomóc. Pytanie jest dość podstawowe.
Przykładowy zestaw danych:
set <- structure(list(VarName = structure(c(1L, 5L, 4L, 2L, 3L),
.Label = c("Apple/Blue/Nice",
"Apple/Blue/Ugly", "Apple/Pink/Ugly", "Kiwi/Blue/Ugly", "Pear/Blue/Ugly"
), class = "factor"), Color = structure(c(1L, 1L, 1L, 1L, 2L), .Label = c("Blue",
"Pink"), class = "factor"), Qty = c(45L, 34L, 46L, 21L, 38L)), .Names = c("VarName",
"Color", "Qty"), class = "data.frame", row.names = c(NA, -5L))
Daje to zestaw danych, taki jak:
set
VarName Color Qty
1 Apple/Blue/Nice Blue 45
2 Pear/Blue/Ugly Blue 34
3 Kiwi/Blue/Ugly Blue 46
4 Apple/Blue/Ugly Blue 21
5 Apple/Pink/Ugly Pink 38
To, co chciałbym zrobić, jest dość proste. Chciałbym zsumować (lub średnie lub stdev) kolumnę Qty. Ale również chciałbym wykonać tę samą operację pod następującymi warunkami:
- VarName zawiera „Jabłko”
- VarName zawiera „Brzydkie”
- Kolor to „Niebieski”
Ktoś, kto może mi szybko przedstawić, jak wykonywać tego rodzaju obliczenia?
Zdaję sobie sprawę, że część z nich można wykonać za pomocą funkcji agregacji(), np.:
aggregate(set[3], FUN=sum, by=set[2])[1,2]
Uważam jednak, że istnieje prostszy sposób na zrobienie tego niż ten. Czy są jakieś filtry, które można dodać do funkcji takich jak sum()
?
2 odpowiedzi
Czy to jest to, czego szukasz?
# sum for those including 'Apple'
apple <- set[grep('Apple', set[, 'VarName']), ]
aggregate(apple[3], FUN=sum, by=apple[2])
Color Qty
1 Blue 66
2 Pink 38
# sum for those including 'Ugly'
ugly <- set[grep('Ugly', set[, 'VarName']), ]
aggregate(ugly[3], FUN=sum, by=ugly[2])
Color Qty
1 Blue 101
2 Pink 38
# sum for Color==Blue
sum(set[set[, 'Color']=='Blue', 3])
[1] 146
Ostatnią sumę można zrobić za pomocą subset
sum(subset(set, Color=='Blue')[,3])
Najprostszy sposób na podzielenie kolumny VarName
, a następnie tworzenie podzbiorów staje się bardzo łatwe. Stwórzmy więc obiekt, w którym varName
został oddzielony:
##There must(?) be a better way than this. Anyone?
new_set = t(as.data.frame(sapply(as.character(set$VarName), strsplit, "/")))
Krótkie wyjaśnienie:
- Używamy
as.character
, ponieważset$VarName
jest czynnikiem sapply
przyjmuje kolejno każdą wartość i stosujestrplit
- Funkcja
strsplit
dzieli elementy - Konwertujemy do ramki danych
- Transpozycja, aby uzyskać prawidłową rotację
Kolejny,
##Convert to a data frame
new_set = as.data.frame(new_set)
##Make nice rownames - not actually needed
rownames(new_set) = 1:nrow(new_set)
##Add in the Qty column
new_set$Qty = set$Qty
To daje
R> new_set
V1 V2 V3 Qty
1 Apple Blue Nice 45
2 Pear Blue Ugly 34
3 Kiwi Blue Ugly 46
4 Apple Blue Ugly 21
5 Apple Pink Ugly 38
Teraz wszystkie operacje są standardowe. Na przykład,
##Add up all blue Qtys
sum(new_set[new_set$V2 == "Blue",]$Qty)
[1] 146
##Average of Blue and Ugly Qtys
mean(new_set[new_set$V2 == "Blue" & new_set$V3 == "Ugly",]$Qty)
[1] 33.67
Gdy będzie w prawidłowej formie, możesz użyć ddply
, co robi, co chcesz (i nie tylko)
library(plyr)
##Split the data frame up by V1 and take the mean of Qty
ddply(new_set, .(V1), summarise, m = mean(Qty))
##Split the data frame up by V1 & V2 and take the mean of Qty
ddply(new_set, .(V1, V2), summarise, m = mean(Qty))
Podobne pytania
Nowe pytania
r
R to darmowy język programowania typu open source i środowisko oprogramowania do obliczeń statystycznych, bioinformatyki, wizualizacji i obliczeń ogólnych. Proszę podać minimalne i powtarzalne przykłady wraz z pożądanymi wynikami. Użyj dput () dla danych i określ wszystkie pakiety inne niż podstawowe za pomocą wywołań biblioteki (). Nie osadzaj obrazów dla danych lub kodu, zamiast tego użyj wciętych bloków kodu. W przypadku pytań związanych ze statystykami należy skorzystać z https://stats.stackexchange.com.