首页 > 解决方案 > 在 Python 3.x 中使用 Pandas 根据列条件和特定列的值合并两个 DataFrame

问题描述

参考我几天前提出的问题,我现在的数据还有一个问题。我有以下两个数据框:

    >>> df1
        A  B   date
   0    1  1   2015-02
   1    1  1   2015-03
   2    2  2   2017-01
   3    2  2   2017-02

    >>> df2
        A  B  C            02-2015  03-2015   01-2017   02-2017
   0    1  1  2013-07-01   0.10     0.22      0.55      0.77
   1    1  1  2015-01-01   0.20     0.12      0.99      0.125
   2    2  2  2016-12-01   0.13     0.15      0.15      0.245
   3    2  2  2016-01-01   0.33     0.1       0.888     0.64

我想要的是跟随DataFrame:

    >>> df1
        A  B   date      value
   0    1  1   2015-02   0.20
   1    1  1   2015-03   0.12
   2    2  2   2017-01   0.15
   3    2  2   2017-02   0.245

我当前的代码如下所示:

df1['value'] = df2.set_index('A', 'B').lookup(
            df1.set_index('A', 'B').index, df1['date'])

这不起作用,我的 df1 是 NoneType 因为在 df2 中是条件 A 和 B == 1 的重复行。我想要的是一个附加条件,它首先提取每个 unqiue A 和 B 的最早日期,这将是A 和 B == 1 日期为 2015-02。

从 df2 开始,它应该取第 1 行,因为月份中的增量仅为 1,而不是第 0 行,增量为 18。

提前谢谢了!

标签: pythonpandasdataframemergemapping

解决方案


可以通过melt, lambda, sort_values, drop_dulicates如下方式实现

df3 = df2.melt(id_vars = ['A', 'B', 'C'], var_name='date')
df3[['A', 'B']] = df3[['A', 'B']].astype(float)
df3['Diff'] = df3.apply(lambda row: abs(datetime.strptime(row['date'], '%Y-%m') - datetime.strptime(row['C'], '%Y-%m-%d')), axis=1)
df3.sort_values(['Diff'], ascending=[True], inplace=True)
df3.drop_duplicates(subset=['A', 'B', 'date'], keep='first', inplace=True)
df3.drop(['C', 'Diff'], 1, inplace=True)
df4 = df1.merge(df3, on=['A', 'B', 'date'], how='left')

输出是

A    B     date  value
0  1.0  1.0  2015-02  0.200
1  1.0  1.0  2015-03  0.120
2  2.0  2.0  2017-01  0.150
3  2.0  2.0  2017-02  0.245

完整的例子如下。

import pandas as pd
from datetime import datetime

df1 = pd.DataFrame(columns = ['A', 'B', 'date'])
df1.loc[len(df1)] = [1, 1, '2015-02']
df1.loc[len(df1)] = [1, 1, '2015-03']
df1.loc[len(df1)] = [2, 2, '2017-01']
df1.loc[len(df1)] = [2, 2, '2017-02']
df1[['A', 'B']] = df1[['A', 'B']].astype(float)

df2 = pd.DataFrame(columns = ['A', 'B', 'C', '2015-02', '2015-03', '2017-01', '2017-02'])
df2.loc[len(df2)] = [1, 1, '2013-07-01', 0.10, 0.22, 0.55, 0.77]
df2.loc[len(df2)] = [1, 1, '2015-01-01', 0.20, 0.12, 0.99, 0.125]
df2.loc[len(df2)] = [2, 2, '2016-12-01', 0.13, 0.15, 0.15, 0.245]
df2.loc[len(df2)] = [2, 2, '2016-01-01', 0.33, 0.1, 0.888, 0.64]

df3 = df2.melt(id_vars = ['A', 'B', 'C'], var_name='date')
df3[['A', 'B']] = df3[['A', 'B']].astype(float)
df3['Diff'] = df3.apply(lambda row: abs(datetime.strptime(row['date'], '%Y-%m') - datetime.strptime(row['C'], '%Y-%m-%d')), axis=1)
df3.sort_values(['Diff'], ascending=[True], inplace=True)
df3.drop_duplicates(subset=['A', 'B', 'date'], keep='first', inplace=True)
df3.drop(['C', 'Diff'], 1, inplace=True)
df4 = df1.merge(df3, on=['A', 'B', 'date'], how='left')
print(df4)

推荐阅读