2017-12-21 29 views
7

Python Pandasでは、私はDataFrameを持っています。このDataFrameを列でグループ化し、列の最後の値を別の列のすべての行に割り当てたいとします。Python Pandas:そのグループのすべてのエントリにDataFrame Groupの最終値を割り当てます。

私は、このコマンドによって、グループの最後の行を選択することが可能だということを知っている:

import pandas as pd 

df = pd.DataFrame({'a': (1,1,2,3,3), 'b':(20,21,30,40,41)}) 
print(df) 
print("-") 
result = df.groupby('a').nth(-1) 
print(result) 

結果:

a b 
0 1 20 
1 1 21 
2 2 30 
3 3 40 
4 3 41 
- 
    b 
a  
1 21 
2 30 
3 41 

どのようにこの操作の結果を割り当てることも可能であろう元のデータフレームに戻って、私は次のようになります:

a b b_new 
0 1 20 21 
1 1 21 21 
2 2 30 30 
3 3 40 41 
4 3 41 41 

答えて

4

と:

df['b_new'] = df.groupby('a')['b'].transform('last') 

オルタナティブ:nthjoin

df['b_new'] = df.groupby('a')['b'].transform(lambda x: x.iat[-1]) 

print(df) 
    a b b_new 
0 1 20  21 
1 1 21  21 
2 2 30  30 
3 3 40  41 
4 3 41  41 

ソリューション:

df = df.join(df.groupby('a')['b'].nth(-1).rename('b_new'), 'a') 
print(df) 
    a b b_new 
0 1 20  21 
1 1 21  21 
2 2 30  30 
3 3 40  41 
4 3 41  41 

タイミング

N = 10000 

df = pd.DataFrame({'a':np.random.randint(1000,size=N), 
        'b':np.random.randint(10000,size=N)}) 

#print (df) 


def f(df): 
    return df.join(df.groupby('a')['b'].nth(-1).rename('b_new'), 'a') 

#cᴏʟᴅsᴘᴇᴇᴅ1 
In [211]: %timeit df['b_new'] = df.a.map(df.groupby('a').b.nth(-1)) 
100 loops, best of 3: 3.57 ms per loop 

#cᴏʟᴅsᴘᴇᴇᴅ2 
In [212]: %timeit df['b_new'] = df.a.replace(df.groupby('a').b.nth(-1)) 
10 loops, best of 3: 71.3 ms per loop 

#jezrael1 
In [213]: %timeit df['b_new'] = df.groupby('a')['b'].transform('last') 
1000 loops, best of 3: 1.82 ms per loop 

#jezrael2 
In [214]: %timeit df['b_new'] = df.groupby('a')['b'].transform(lambda x: x.iat[-1]) 
10 loops, best of 3: 178 ms per loop 

#jezrael3 
In [219]: %timeit f(df) 
100 loops, best of 3: 3.63 ms per loop 

警告は

結果は、これらのソリューションのいくつかのためにタイミングをたくさん影響するグループの数、与えられたパフォーマンスを扱っていません。

6

2つの可能性、groupby + nth + mapまたはreplace

df['b_new'] = df.a.map(df.groupby('a').b.nth(-1)) 

あるいは、

df['b_new'] = df.a.replace(df.groupby('a').b.nth(-1)) 

であなたはまた、last()nth(-1)を置き換えることができます(実際には、そうすることが、これは少し作るために起こりますnth)は、bの各グループからどのアイテムを選ぶかをより柔軟にすることができます。


df 

    a b b_new 
0 1 20  21 
1 1 21  21 
2 2 30  30 
3 3 40  41 
4 3 41  41 
2

私は、これは速い

df.merge(df.drop_duplicates('a',keep='last'),on='a',how='left') 
Out[797]: 
    a b_x b_y 
0 1 20 21 
1 1 21 21 
2 2 30 30 
3 3 40 41 
4 3 41 41 
されるべきだと思う
関連する問題