2017-08-08 4 views
1

In R, wenn ich die Datenrahmen haben:Split Differenz von gegebenen Spalte innerhalb zweireihigen Gruppen

a <- c(1,1,2,2,3,3,4,4);b <- c(1,0,1,0,1,0,1,0); c <- c(1.5,2.5,30,20,100,150,0.7,0.3)  
df <- data.frame(a,b,c) 
> df 
    a b  c 
1 1 1 1.5 
2 1 0 2.5 
3 2 1 30.0 
4 2 0 20.0 
5 3 1 100.0 
6 3 0 150.0 
7 4 1 0.7 
8 4 0 0.3 

I die Differenz innerhalb von Gruppen in einem vektorisierten Weise aufspalten:

df$d <- ifelse(df$b == 1, (df$c - c(df$c[-1], NA))/2, (df$c - c(NA, df$c[-nrow(df)]))/2) 
> df 
    a b  c  d 
1 1 1 1.5 -0.5 
2 1 0 2.5 0.5 
3 2 1 30.0 5.0 
4 2 0 20.0 -5.0 
5 3 1 100.0 -25.0 
6 3 0 150.0 25.0 
7 4 1 0.7 0.2 
8 4 0 0.3 -0.2 

Gibt es Ein ähnlicher Weg, um diese Ergebnisse mit dem gleichen Datenrahmen in Pandas zu erreichen?

df = pd.DataFrame({'a': [1,1,2,2,3,3,4,4], 'b': [1,0,1,0,1,0,1,0], 'c': [1.5,2.5,30,20,100,150,0.7,0.3]}) 

Antwort

3

Angenommen es gibt nur 2 Zeilen pro Gruppe, dann ist dies einfach der Unterschied zum Mittelwert. Ich verwende assign, um eine Kopie des Datenrahmens zu erstellen und der Kopie eine neue Spalte zuzuweisen.

df.assign(d=df.groupby('a').c.transform('mean').rsub(df.c)) 

    a b  c  d 
0 1 1 1.5 -0.5 
1 1 0 2.5 0.5 
2 2 1 30.0 5.0 
3 2 0 20.0 -5.0 
4 3 1 100.0 -25.0 
5 3 0 150.0 25.0 
6 4 1 0.7 0.2 
7 4 0 0.3 -0.2 

Sie könnten die gleiche Sache an Ort und Stelle erreichen

df['d'] = df.groupby('a').c.transform('mean').rsub(df.c) 
+0

Danke, ich habe gerade versucht, den Code, ich glaube, Sie statt Unter benötigen Rsub aber geniale Lösung – Tony

+0

@Tony danke, ja, habe ich 'rsub' in einem Teil aber nicht der andere. Danke für den Fang. – piRSquared

3

1. Mit np.where und .shift

In [1238]: df['d'] = np.where(df.b ==1, 
           (df.c - df.c.shift(-1))/2, 
           (df.c - df.c.shift(1))/2) 

In [1239]: df 
Out[1239]: 
    a b  c  d 
0 1 1 1.5 -0.5 
1 1 0 2.5 0.5 
2 2 1 30.0 5.0 
3 2 0 20.0 -5.0 
4 3 1 100.0 -25.0 
5 3 0 150.0 25.0 
6 4 1 0.7 0.2 
7 4 0 0.3 -0.2 

2. Oder verwenden df.c.diff(n) statt df.c - df.c.shift(n)

In [1244]: np.where(df.b ==1, df.c.diff(-1)/2, df.c.diff(1)/2) 
Out[1244]: array([ -0.5, 0.5, 5. , -5. , -25. , 25. , 0.2, -0.2]) 
1

Für Sie R-Code, können Sie dies ändern.

df%>%group_by(a)%>%dplyr::mutate(A=ifelse(b==1,(c-shift(c,1,type='lead'))/2,(c-shift(c,1,type = 'lag'))/2)) 
# A tibble: 8 x 4 
# Groups: a [4] 
     a  b  c  A 
    <dbl> <dbl> <dbl> <dbl> 
1  1  1 1.5 -0.5 
2  1  0 2.5 0.5 
3  2  1 30.0 5.0 
4  2  0 20.0 -5.0 
5  3  1 100.0 -25.0 
6  3  0 150.0 25.0 
7  4  1 0.7 0.2 
8  4  0 0.3 -0.2 

Für Python,

df['d']=-df.groupby('a')['c'].diff().bfill()/2*df.b.replace({0:-1}) 


Out[95]: 
    a b  c  d 
0 1 1 1.5 -0.5 
1 1 0 2.5 0.5 
2 2 1 30.0 5.0 
3 2 0 20.0 -5.0 
4 3 1 100.0 -25.0 
5 3 0 150.0 25.0 
6 4 1 0.7 0.2 
7 4 0 0.3 -0.2 
Verwandte Themen