首页 > 解决方案 > 如何将 Pandas DataFrame 与列表的字典合并

问题描述

合并df这样的最佳方法是什么:

+------------+----------+
| domain     | username |
+------------+----------+
| @gmail.com | gagaga   |
+------------+----------+
| @mail.com  | bobo     |
+------------+----------+

像这样的字典:

domain_to_app = {
    '@gmail.com': ['gmail', 'youtube', 'gdrive'],
    '@mail.com': ['email', 'dropbox']
}

得到这个:

+------------+----------+-----------+
| domain     | username | app       |
+------------+----------+-----------+
| @gmail.com | gagaga   | gmail     |
+------------+----------+-----------+
| @gmail.com | gagaga   | youtube   |
+------------+----------+-----------+
| @gmail.com | gagaga   | gdrive    |
+------------+----------+-----------+
| @mail.com  | bobo     | email     |
+------------+----------+-----------+
| @mail.com  | bobo     | dropbox   |
+------------+----------+-----------+

是否建议将其转换dictdf重复行并使用merge,或者我应该使用map然后取消堆叠应用程序列

标签: pythonpandasdataframe

解决方案


您可以使用mapfor new Series,然后chain.from_iterable使用repeatfor new DataFrame

s = df['domain'].map(domain_to_app)

from itertools import chain

lens = s.str.len()
df = pd.DataFrame({
    'domain' : df['domain'].values.repeat(lens),
    'username' : df['username'].values.repeat(lens),
     'app' : list(chain.from_iterable(s))
})

print (df)
       domain username      app
0  @gmail.com   gagaga    gmail
1  @gmail.com   gagaga  youtube
2  @gmail.com   gagaga   gdrive
3   @mail.com     bobo    email
4   @mail.com     bobo  dropbox

如果需要重复DaatFramemapped值创建的多个列,请通过以下方式重塑stack和“重复” join

df['app'] = df['domain'].map(domain_to_app)

df = (df.join(pd.DataFrame(df.pop('app')
                            .values.tolist())
               .stack()
               .reset_index(level=1, drop=True)
               .rename('app'))).reset_index(drop=True)
print (df)
       domain username      app
0  @gmail.com   gagaga    gmail
1  @gmail.com   gagaga  youtube
2  @gmail.com   gagaga   gdrive
3   @mail.com     bobo    email
4   @mail.com     bobo  dropbox

推荐阅读