панды: перечислять предметы в каждой группе - PullRequest
0 голосов
/ 10 сентября 2018

У меня есть DataFrame вроде

    id   chi  prop   ord 
0   100   L    67     0 
1   100   L    68     1 
2   100   L    68     2 
3   100   L    68     3 
4   100   L    70     0 
5   100   L    71     0 
6   100   R    67     0 
7   100   R    68     1 
8   100   R    68     2 
9   100   R    68     3 
10  110   R    70     0 
11  110   R    71     0 
12  101   L    67     0 
13  101   L    68     0 
14  101   L    69     0 
15  101   L    71     0 
16  101   L    72     0 
17  201   R    67     0 
18  201   R    68     0 
19  201   R    69     0

ord по существу дает порядок записей, когда (prop, chi и id) имеют одинаковое значение. Это не совсем то, что я хотел бы, хотя. Вместо этого я хотел бы иметь возможность перечислять записи каждой группы g в {(id, chi)} от 0 до n_g, где n_g - размер группы g. Поэтому я хотел бы получить что-то похожее на

    id   chi  prop   count 
0   100   L    67     0 
1   100   L    68     1 
2   100   L    68     2 
3   100   L    68     3 
4   100   L    70     4 
5   100   L    71     5 
6   100   R    67     0 
7   100   R    68     1 
8   100   R    68     2 
9   100   R    68     3 
10  110   R    70     0 
11  110   R    71     1 
12  101   L    67     0 
13  101   L    68     1 
14  101   L    69     2 
15  101   L    71     3 
16  101   L    72     4 
17  201   R    67     0 
18  201   R    68     1 
19  201   R    69     2

Я бы хотел знать, есть ли простой способ сделать это с pandas. Следующее очень близко подходит, но оно кажется слишком сложным, и по какой-то причине оно не позволит мне join получить итоговый фрейм данных с оригинальным.

(df.groupby(['id', 'chi'])
   .apply(lambda g: np.arange(g.shape[0]))
   .apply(pd.Series, 1)
   .stack()
   .rename('counter')
   .reset_index()         
   .drop(columns=['level_2']))

РЕДАКТИРОВАТЬ: Вторым способом, конечно, является цикл for, но я ищу что-то более "Pythonic", чем:

for gname, idx in df.groupby(['id','chi']).groups.items():
    tmp = df.loc[idx]
    df.loc[idx, 'counter'] = np.arange(tmp.shape[0])

R имеет очень простой способ добиться такого поведения с помощью пакетов tidyverse, но я не совсем нашел хорошо отлаженный способ добиться того же с помощью pandas. Будем благодарны за любую помощь!

1 Ответ

0 голосов
/ 10 сентября 2018

cumcount

df.assign(ord=df.groupby(['id', 'chi']).cumcount())

     id chi  prop  ord
0   100   L    67    0
1   100   L    68    1
2   100   L    68    2
3   100   L    68    3
4   100   L    70    4
5   100   L    71    5
6   100   R    67    0
7   100   R    68    1
8   100   R    68    2
9   100   R    68    3
10  110   R    70    0
11  110   R    71    1
12  101   L    67    0
13  101   L    68    1
14  101   L    69    2
15  101   L    71    3
16  101   L    72    4
17  201   R    67    0
18  201   R    68    1
19  201   R    69    2

defaultdict и count

from itertools import count
from collections import defaultdict

d = defaultdict(count)

df.assign(ord=[next(d[t]) for t in zip(df.id, df.chi)])

     id chi  prop  ord
0   100   L    67    0
1   100   L    68    1
2   100   L    68    2
3   100   L    68    3
4   100   L    70    4
5   100   L    71    5
6   100   R    67    0
7   100   R    68    1
8   100   R    68    2
9   100   R    68    3
10  110   R    70    0
11  110   R    71    1
12  101   L    67    0
13  101   L    68    1
14  101   L    69    2
15  101   L    71    3
16  101   L    72    4
17  201   R    67    0
18  201   R    68    1
19  201   R    69    2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...