выполните df.loc для groupby df

#python #pandas #dataframe #pandas-groupby

Вопрос:

У меня df есть список личности, происхождения и места назначения

 df = pd.DataFrame({'PersonID':['1','1','2','2','2','3'],'O':['A','B','C','B','A','X'],'D':['B','A','B','A','B','Y']})
 

в df:

 PersonID    O       D
   1        A       B
   1        B       A      
   2        C       B
   2        B       A
   2        A       B
   3        X       Y
 

Я сгруппировал их по df df_grouped = df.groupby(['O','D']) и сопоставил их с другим фреймом данных, taxi .

 TaxiID    O       D
  T1      B       A
  T2      A       B
  T3      C       B
 

точно так же я группируюсь по taxi своим O и D . Затем я объединил их после объединения и подсчета идентификаторов персон и таксидов на пару O-D. Я сделал это, чтобы посмотреть, сколько такси доступно для скольких людей.

 O     D     PersonID    TaxiID
             count      count
A     B        2          1
B     A        2          1
C     B        1          1
 

Теперь я хочу выполнить df.loc , чтобы взять только те идентификаторы персон, которые были учтены в объединенном файле. Как я могу это сделать? Я пытался нам:

 seek = df.loc[df.PersonID.isin(merged['PersonID'])]
 

но он возвращает пустой фрейм данных. Что я могу сделать для этого?

редактировать: я прилагаю полный код для этого случая, используя фиктивные данные

 df = pd.DataFrame({'PersonID':['1','1','2','2','2','3'],'O':['A','B','C','B','A','X'],'D':['B','A','B','A','B','Y']})
taxi = pd.DataFrame({'TaxiID':['T1','T2','T3'],'O':['B','A','C'],'D':['A','B','B']})

df_grouped = df.groupby(['O','D'])
taxi_grouped = taxi.groupby(['O','D'])

dfm = df_grouped.agg({'PersonID':['count',list]}).reset_index()
tgm = taxi_grouped.agg({'TaxiID':['count',list]}).reset_index()

merged = pd.merge(dfm, tgm, how='inner')

seek = df.loc[df.PersonID.isin(merged['PersonID'])]
 

Комментарии:

1. Можете ли вы показать свой полный код?

2. @jezrael Я отредактировал его и добавил полный код

Ответ №1:

Выберите MultiIndex tuple с Series.explode помощью для скаляров из вложенных списков:

 seek = df.loc[df.PersonID.isin(merged[('PersonID', 'list')].explode().unique())]
print (seek)
  PersonID  O  D
0        1  A  B
1        1  B  A
2        2  C  B
3        2  B  A
4        2  A  B
 

Для повышения производительности возможно использование set comprehension с выравниванием:

 seek = df.loc[df.PersonID.isin(set(z for x in merged[('PersonID', 'list')] for z in x))]
print (seek)
  PersonID  O  D
0        1  A  B
1        1  B  A
2        2  C  B
3        2  B  A
4        2  A  B
 

Комментарии:

1. Я ожидаю, что его будет быстрее использовать merged[('PersonID', 'list')].explode().unique() для больших кадров данных.

2. @mozway — я, согласен.

3. @mozway @jezrael это прекрасно работает, спасибо! таким образом, в основном то, что он сделал, состояло в преобразовании merged['PersonID'] в список, а затем в df.loc получении данных из df с этим списком в качестве ссылки. Верна ли моя интерпретация?

4. @Ricky Вы близки, это массив numpy, подобный списку для первого решения, для второго он задан для справки.