объединить результаты группы непосредственно обратно в фрейм данных - PullRequest
0 голосов
/ 27 апреля 2018

Предположим, у меня есть следующие данные:

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

Фрейм данных отсортирован по двум идентификаторам. Предположим, я хотел бы знать значение x ПЕРВОГО наблюдения в каждой группе id1 наблюдений. Результат будет как

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 голосов
/ 27 апреля 2018

Поскольку при построении значений для каждой строки необходимо учитывать весь фрейм данных, необходим промежуточный шаг.

Следующее получает ваше значение 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])
0 голосов
/ 03 мая 2018

Я думаю, что проще всего это transform с first:

df['first_x'] = df.groupby('id1')['x'].transform('first')

Или map от Series, созданного drop_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
0 голосов
/ 27 апреля 2018

Как то так?

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')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...