将groupby结果直接返回到数据帧

时间:2018-04-27 11:44:48

标签: python pandas pandas-groupby

假设我有以下数据:

df = pd.DataFrame(data = [[1,1,10],[1,2,20],[1,3,50],[2,1,15],[2,2,20],[2,3,30],[3,1,40],[3,2,70]],columns=['id1','id2','x'])


   id1  id2   x
0    1    1  10
1    1    2  20
2    1    3  50
3    2    1  15
4    2    2  20
5    2    3  30
6    3    1  40
7    3    2  70

数据框沿两个ID排序。假设我想知道每组id1观察中第一次观察的x的值。结果就像

id1 id2 x   first_x
1   1   10  10
1   2   30  10
1   3   50  10
2   1   15  15
2   2   20  15
2   3   30  15
3   1   40  40
3   2   70  40

我如何实现这个'下标'?理想情况下,每个观察点都会填充新列。

我想的是

df['first_x'] = df.groupby(['id1'])[0]

3 个答案:

答案 0 :(得分:1)

这样的东西?

df = pd.DataFrame(data = [[1,1,10],[1,2,20],[1,3,50],[2,1,15],[2,2,20],[2,3,30],[3,1,40],[3,2,70]],columns=['id1','id2','x'])
df = df.join(df.groupby(['id1'])['x'].first(), on='id1', how='left', lsuffix='', rsuffix='_first')

答案 1 :(得分:1)

在构建每行的值时需要考虑整个数据帧,需要一个中间步骤。

以下内容使用group by获取first_x值,然后将其用作地图以添加新列。

import pandas as pd

df = pd.DataFrame(data = [[1,1,10],[1,2,20],[1,3,50],[2,1,15],[2,2,20],[2,3,30],[3,1,40],[3,2,70]],columns=['id1','id2','x'])

first_xs = df.groupby(['id1']).first().to_dict()['x']

df['first_x'] = df['id1'].map(lambda id: first_xs[id])

答案 2 :(得分:1)

我认为最简单的是transform first

Series

mapdrop_duplicates创建的df['first_x'] = df['id1'].map(df.drop_duplicates('id1').set_index('id1')['x']) print (df) id1 id2 x first_x 0 1 1 10 10 1 1 2 20 10 2 1 3 50 10 3 2 1 15 15 4 2 2 20 15 5 2 3 30 15 6 3 1 40 40 7 3 2 70 40

np.random.seed(123)
N = 1000000
L = list('abcde') 
df = pd.DataFrame({'id1': np.random.randint(10000,size=N),
                   'x':np.random.randint(10000,size=N)})
df = df.sort_values('id1').reset_index(drop=True)
print (df)

In [179]: %timeit df.join(df.groupby(['id1'])['x'].first(), on='id1', how='left', lsuffix='', rsuffix='_first')
10 loops, best of 3: 125 ms per loop

In [180]: %%timeit
     ...: first_xs = df.groupby(['id1']).first().to_dict()['x']
     ...: 
     ...: df['first_x'] = df['id1'].map(lambda id: first_xs[id])
     ...: 
1 loop, best of 3: 524 ms per loop

In [181]: %timeit df['first_x'] = df.groupby('id1')['x'].transform('first')
10 loops, best of 3: 54.9 ms per loop

In [182]: %timeit df['first_x'] = df['id1'].map(df.drop_duplicates('id1').set_index('id1')['x'])
10 loops, best of 3: 142 ms per loop

首先是最短且最快的解决方案:

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
相关问题