2016-05-18 12 views
0

Hier ist meine Daten:Reihenfolge gefolgt von kumulativer Summe + von

class x1 x2 
c  6 90 
b  5 50 
c  3 70 
b  9 40 
a  5 30 
b  1 60 
a  7 20 
c  4 80 
a  2 10 

Ich mag zuerst bestellen, indem class (Erhöhung oder Verringerung spielt keine Rolle) und dann durch x1 (absteigend), so dass ich wie folgt vorgehen:

df <- df[with(df, order(class, x1, decreasing = TRUE))] 

class x1 x2 
c  6 90 
c  4 80 
c  3 70 
b  9 40 
b  5 50 
b  1 60 
a  7 20 
a  5 30 
a  2 10 

Und dann würde ich die kumulative Summe über x1 für jeden class mag:

class x1 x2 cumsum 
c  6 90 90  
c  4 80 170  # 90+80 
c  3 70 240  # 90+80+70 
b  9 40 40  
b  5 50 90  # 40+50 
b  1 60 150  # 40+50+60 
a  7 20 20 
a  5 30 50  # 20+30 
a  2 10 60  # 20+30+10 

Nach this answer, tat ich dies:

df$cumsum <- unlist(by(df$x2, df$class, cumsum)) 
# (Also tried this, same result) 
df$cumsum <- unlist(by(df[,x2], df[,class], cumsum)) 

Aber was ich bekommen, ist eine kumulative Summe über den gesamten Satz + misordered. Um genauer zu sein, hier ist, was ich bekomme:

class x1 x2 cumsum 
c  6 90 20 # this cumsum 
c  4 80 50 # and this cumsum 
c  3 70 60 # and this cumsum are the cumsum of the lines of class a, 
b  9 40 100 # then it adds the 'x2' values of class b : 60 ('cumsum' from the previous line) + 40 
b  5 50 150 # and keeps doing so : 100 + 50 
b  1 60 210 # 150 + 60 
a  7 20 300 # 210 + 90 
a  5 30 380 # 300 + 80 
a  2 10 450 # 380 + 70 

Eine Idee, wie ich das lösen könnte? Dank

Antwort

2

Wir data.table

library(data.table) 
setDT(df)[, x2:= cumsum(x2) , class] 
df 
# class x1 x2 
#1:  c 6 90 
#2:  c 4 170 
#3:  c 3 240 
#4:  b 9 40 
#5:  b 5 90 
#6:  b 1 150 
#7:  a 7 20 
#8:  a 5 50 
#9:  a 2 60 

Hinweis verwenden: In der obigen ich die bestellten Daten verwendet Wenn wir auch order benötigen,

setorder(setDT(df), -class, -x1)[, x2:=cumsum(x2), class] 
+1

Oder 'setDT (df) [bestellen (-Klasse, -X1), x2: = cumsum (x2), durch = Klasse] ', die auch die ursprüngliche Reihenfolge von" df "beibehalten wird. – Arun

+1

@Arun Danke, ich dachte auf diese Weise, aber später dachte ich, dass der OP die Reihen neu anordnen wollte. – akrun

+0

Akrun, ah ich sehe .. in Ordnung. – Arun

2

dplyr können hier arbeiten zu

library(dplyr) 

df %>% 
    group_by(class) %>% 
    arrange(desc(x1)) %>% 
    mutate(cumsum=cumsum(x2)) 

## class x1 x2 cumsum 
## (fctr) (int) (int) (int) 
## 1  a  7 20  20 
## 2  a  5 30  50 
## 3  a  2 10  60 
## 4  b  9 40  40 
## 5  b  5 50  90 
## 6  b  1 60 150 
## 7  c  6 90  90 
## 8  c  4 80 170 
## 9  c  3 70 240 

Wie beschrieben hier (https://cran.rstudio.com/web/packages/dplyr/vignettes/introduction.html) und anderswo impliziert die group_by in Verbindung mit arrange, dass die Daten zuerst nach der Gruppierungsvariablen sortiert werden.

+0

ok meine gelöscht, wie Sie mich für ein paar Sekunden zu schlagen :) – Sotos

0

Sie Basis R transform und ave-cumsum über die class Spalte verwenden können

transform(df[order(df$class, decreasing = T), ], cumsum = ave(x2, class, FUN=cumsum)) 


# class x1 x2 cumsum 
#1  c 6 90  90 
#3  c 3 70 160 
#8  c 4 80 240 
#2  b 5 50  50 
#4  b 9 40  90 
#6  b 1 60 150 
#5  a 5 30  30 
#7  a 7 20  50 
#9  a 2 10  60 
Verwandte Themen