2017-08-08 126 views
1

在R,如果我有數據幀:分裂差

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 

我可以在向量化方式拆分組內的差異:

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 

是否有在熊貓中使用相同的數據框來實現這些結果的相似方法?

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]}) 

回答

3

假設每組只有2行,那麼這只是與平均值的差異。我使用assign來創建數據框的副本併爲副本分配一個新列。

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 

你可以做到相同的事情到位

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

謝謝,我只是想你的代碼,我認爲你需要RSUB,而不是分而輝煌的解決方案 – Tony

+0

@Tony感謝,是的,我把'rsub'在一個部分但不是其他。謝謝你的收穫。 – piRSquared

3

使用np.where.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.或者使用df.c.diff(n)代替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

對於您的R代碼,您可以更改爲此。

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 

對於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