Pandas: объединить многоуровневый индекс так, чтобы другой Dataframe имел различную сортировку - PullRequest
1 голос
/ 13 февраля 2020

Предположим, у вас есть следующие два кадра данных dfs и df1

dfs определяется как

dfs=pd.DataFrame({
    'Year':[2006, 2006, 2006, 2006, 2006], 
    'Provider':list('abcsd'),
    'Accepted': [2570, 1020, 2140, 120, 15]
 }) 

dfs=dfs.groupby(['Year', 'Provider']).sum()

df1 определяется как

df1=pd.DataFrame({
    'Year':[2006, 2006, 2006, 2006, 2006], 
    'Provider':list('aabbc'),
    'Gender': list('mfmfm'),
    'Accepted app': ['990', '1180', '435', '405', '985']
 })

I хочу объединить эти два кадра данных, чтобы получить что-то вроде

df2=pd.DataFrame({
    'Year':[2006, 2006, 2006, 2006, 2006,2006, 2006, 2006, 2006, 2006], 
    'Provider':list('abcsdabcsd'),
    'Accepted': [2570, 1020, 2140, 120, 15,2570, 1020, 2140, 120, 15],
    'Gender': ['m', 'm', 'm', 'Nan', 'Nan', 'f', 'f', 'Nan', 'Nan', 'Nan'],
    'Accepted app': ['990', '435', '985', 'Nan', 'Nan','1180', '405', 'Nan', 'Nan', 'Nan']

 }) 

Я не знаю, как сохранить многоуровневый индекс dfs или как их объединить.

1 Ответ

1 голос
/ 13 февраля 2020

Вы можете повторять строки по уникальным значениям Gender, concat, использовать DataFrame.reset_index, а затем merge с левым соединением:

df = (pd.concat([dfs.assign(Gender=c) for c in df1['Gender'].unique()])
        .reset_index()
        .merge(df1, on=['Provider','Year','Gender'], how='left'))
print (df)
   Year Provider  Accepted Gender Accepted app
0  2006        a      2570      m          990
1  2006        b      1020      m          435
2  2006        c      2140      m          985
3  2006        d        15      m          NaN
4  2006        s       120      m          NaN
5  2006        a      2570      f         1180
6  2006        b      1020      f          405
7  2006        c      2140      f          NaN
8  2006        d        15      f          NaN
9  2006        s       120      f          NaN

Если вы хотите также установить для столбца Gender пропущенные значения, можно определить источник новых строк по параметру indicator=True в DataFrame.merge, а затем заменить пропущенными значениями:

df = (pd.concat([dfs.assign(Gender=c) for c in df1['Gender'].unique()])
        .reset_index()
        .merge(df1, on=['Provider','Year','Gender'], how='left', indicator=True)
        .assign(Gender=lambda x: x['Gender'].mask(x['_merge'].eq('left_only')))
        .drop('_merge', axis=1))

print (df)
   Year Provider  Accepted Gender Accepted app
0  2006        a      2570      m          990
1  2006        b      1020      m          435
2  2006        c      2140      m          985
3  2006        d        15    NaN          NaN
4  2006        s       120    NaN          NaN
5  2006        a      2570      f         1180
6  2006        b      1020      f          405
7  2006        c      2140    NaN          NaN
8  2006        d        15    NaN          NaN
9  2006        s       120    NaN          NaN
...