Сравните каждый элемент в группе groupby() с уникальными значениями в этой группе и получите местоположение равенства

#python #pandas #pandas-groupby #unique

#python #pandas #pandas-groupby #уникальный

Вопрос:

У меня есть фрейм данных с объектами и датами для определенного измерения. Для каждого предмета я хочу выяснить, соответствует ли дата в каждой строке группы первой (1), второй (2), третьей (3)… уникальное значение даты для этого объекта.

Чтобы уточнить, это то, что я ищу:

     |subject | date | order|
    |A | 01.01.2020 | 1|
    |A | 01.01.2020 | 1|
    |A | 02.01.2020 | 2|
    |B | 01.01.2020 | 1|
    |B | 02.01.2020 | 2|
    |B | 02.01.2020 | 2|
  

Я думал о чем-то, как показано ниже, но цикл for недопустим в функции apply:

 df['order']=df.groupby(['subject']).apply(lambda x: i if x['date']=value for i, value in enumerate(x['date'].unique()))
  

Есть ли простой способ сделать это?

Ответ №1:

Используйте factorize в GroupBy.transform :

 df['order1']=df.groupby(['subject'])['date'].transform(lambda x: pd.factorize(x)[0])   1
print (df)
  subject        date  order  order1
0       A  01.01.2020      1       1
1       A  01.01.2020      1       1
2       A  02.01.2020      2       2
3       B  01.01.2020      1       1
4       B  02.01.2020      2       2
5       B  02.01.2020      2       2
  

Или вы можете использовать GroupBy.rank , но необходимо преобразовать столбец date в datetimes:

 df['order2']=df.groupby(['subject'])['date'].rank(method='dense')
print (df)
  subject       date  order  order1
0       A 2020-01-01      1     1.0
1       A 2020-01-01      1     1.0
2       A 2020-02-01      2     2.0
3       B 2020-01-01      1     1.0
4       B 2020-02-01      2     2.0
5       B 2020-02-01      2     2.0
  

Разница в решении заключается в изменении порядка datetimes:

 print (df)
  subject       date  order (disregarding temporal order of date)
0       A 2020-01-01      1
1       A 2020-03-01      2 <- changed datetime for sample
2       A 2020-02-01      3
3       B 2020-01-01      1
4       B 2020-02-01      2
5       B 2020-02-01      2

df['order1']=df.groupby(['subject'])['date'].transform(lambda x: pd.factorize(x)[0])   1
df['order2']=df.groupby(['subject'])['date'].rank(method='dense')
print (df)
  subject       date  order  order1  order2
0       A 2020-01-01      1       1     1.0
1       A 2020-03-01      1       2     3.0
2       A 2020-02-01      2       3     2.0
3       B 2020-01-01      1       1     1.0
4       B 2020-02-01      2       2     2.0
5       B 2020-02-01      2       2     2.0
  

В заключение: используйте первый метод, если вас не волнует временной порядок date отражения в order выходных данных, или второй метод, если временный порядок имеет значение и должен отражаться в order выходных данных.