Как объединить Multi Index в pandas с разными уровнями индекса? - PullRequest
0 голосов
/ 30 марта 2020

У меня есть два pandas кадра данных:


df1 = pd.DataFrame({'user_id':['0','0','1','1','2','3','3'],
                  'friend_id':['1','2','3','2','4','4','5'],
                 'date_sent':['01-01-2020','01-01-2020','01-02-2020','01-03-2020','01-02-2020','01-03-2020','01-02-2020'],
                 'date_accepted':['01-01-2020','01-01-2020','01-02-2020',None,'01-10-2020',None,'01-21-2020']})

df2 = pd.DataFrame({'user_id':['1','1','2','2','3','3'],
                  'page_liked':['A','B','A','C','B','D']})

grouped1 = df1.groupby(['user_id','friend_id']).count()
grouped2 = df2.groupby(['user_id','page_liked']).count()
print(grouped1)

output >>>

                  date_sent  date_accepted
user_id friend_id 

0       1                  1              1
        2                  1              1
1       2                  1              0
        3                  1              1
2       4                  1              1
3       4                  1              0
        5                  1              1

grouped2

output >>>
user_id page_liked
1   A
    B
2   A
    C
3   B
    D

Я пытаюсь объединить grouped1.friend_id с grouped2.user_id. Цель состоит в том, чтобы получить следующую таблицу:


user_id friend_id       page_liked

0       1                  A
                           B          
        2                  A      
                           C    
1       2                  A
                           C         
        3                  B
                           D         
2       4                  Na          
3       4                  Na              
        5                  Na         

Я пытался сделать merge несколькими способами, но безуспешно, так как индексы многоуровневые. Я также пробовал grouped1.combine_first(grouped2), но, похоже, это работает только при одинаковых уровнях индекса, поэтому я застрял в данный момент.

Ответы [ 2 ]

0 голосов
/ 31 марта 2020

Используйте join. Он поддерживает мультииндексное объединение данных в мультииндексах.

Вам необходимо изменить имя уровня индекса на grouped2, чтобы оно совпадало с именем уровня индекса на grouped1. Поскольку вы хотите сопоставить на одном уровне индекса, просто измените имя одного уровня. Итак, на grouped2 измените имя уровня user_id на friend_id. Наконец, объединение, изменение порядка уровней индекса, а также reset_index и slice

df_out = grouped1.join(grouped2.rename_axis(['friend_id', 'page_liked']), 
                       how='left').swaplevel(0,1).reset_index(level=-1)[['page_liked']]

Out[82]:
                  page_liked
user_id friend_id
0       1                  A
        1                  B
        2                  A
        2                  C
1       2                  A
        2                  C
        3                  B
        3                  D
2       4                NaN
3       4                NaN
        5                NaN
0 голосов
/ 31 марта 2020

См. Комментарии в ответах для ключевых шагов, используя reset_index (), переименовав столбец и выполнив другую групповую операцию.

import pandas as pd
df1 = pd.DataFrame({'user_id':['0','0','1','1','2','3','3'],
                  'friend_id':['1','2','3','2','4','4','5'],
                 'date_sent':['01-01-2020','01-01-2020','01-02-2020','01-03-2020','01-02-2020','01-03-2020','01-02-2020'],
                 'date_accepted':['01-01-2020','01-01-2020','01-02-2020',None,'01-10-2020',None,'01-21-2020']})
df2 = pd.DataFrame({'user_id':['1','1','2','2','3','3'],
                  'page_liked':['A','B','A','C','B','D']})
#Use reset_index() to change indexes to columns and for group 2 rename the column to match the column you want to merge with
grouped1 = df1.groupby(['user_id','friend_id']).count().reset_index()
grouped2 = df2.groupby(['user_id','page_liked']).count().reset_index().rename(columns={'user_id':'friend_id'})
#merge and drop unnecessary columns and then do another groupby if you want to re-index.
grouped3=pd.merge(grouped1, grouped2, how='left', on=['friend_id']).drop(['date_sent', 'date_accepted'], axis=1)['page_liked'].min())
grouped3
...