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:

  1. VarName zawiera „Jabłko”
  2. VarName zawiera „Brzydkie”
  3. 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()?

0
Jochem 27 wrzesień 2012, 13:32

2 odpowiedzi

Najlepsza odpowiedź

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])
1
Jilber Urbina 27 wrzesień 2012, 14:09

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 stosuje strplit
  • 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))
2
csgillespie 27 wrzesień 2012, 17:38