Python 根据数据框中的行匹配,有条件地使用另一个数据框中的值填充列

Python 根据数据框中的行匹配,有条件地使用另一个数据框中的值填充列,python,pandas,Python,Pandas,我发现自己在试图解决税务文书自动化这个问题时迷失了方向。我有两个数据框:一个是欧元/美元汇率的季度历史记录,另一个是我自己的发票,例如: 作为pd进口熊猫 将numpy作为np导入 usdeur=[pd.时间戳'20170705',1.1329, pd.时间戳'20170706',1.1385, pd.时间戳'20170707',1.1412, pd.时间戳'20170710',1.1387, pd.时间戳'20170711',1.1405, pd.时间戳'20170712',1.1449] 标

我发现自己在试图解决税务文书自动化这个问题时迷失了方向。我有两个数据框:一个是欧元/美元汇率的季度历史记录,另一个是我自己的发票,例如:

作为pd进口熊猫 将numpy作为np导入 usdeur=[pd.时间戳'20170705',1.1329, pd.时间戳'20170706',1.1385, pd.时间戳'20170707',1.1412, pd.时间戳'20170710',1.1387, pd.时间戳'20170711',1.1405, pd.时间戳'20170712',1.1449] 标签=['Date','Rate'] rates=pd.DataFrame.from_recordsusdeur,columns=labels 交易=[pd.时间戳'20170706','PayPal','USD',100,1, pd.时间戳'20170706','Fastspring','USD',200,1, pd.时间戳'20170709','Fastspring','USD',100,1, pd.时间戳'20170710','EU','EUR',100,1, pd.时间戳'20170710','PayPal','USD',200,1] 标签=['Date','From','Currency','Amount','Rate'] sales=pd.DataFrame.from_recordstransactions,columns=labels 导致:

我需要在sales['Rate']栏中填入汇率['Rate']中的正确汇率,也就是说:

如果销售额['Currency']是'EUR',不要管它。 对于每一行销售,在rates中找到与“Date”匹配的行;抓住这个价格['Rate']值,并将其用于销售['Rate'] 奖励:如果没有匹配的“日期”,例如在节假日,交易所市场关闭,请检查前一行,直到找到合适的值。 完整结果应如下所示,第2行的费率为2017-07-07:

我试着从其他问题中找到一些建议的解决方案,但没有成功。
非常感谢您提前

您可以更改您的费率数据框以包含所有日期,然后向前填充,在费率数据框中创建一个名为“货币”的列,然后在日期和货币列上加入两个df

idx = pd.DataFrame(pd.date_range('2017-07-05', '2017-07-12'),columns=['Date'])
rates = pd.merge(idx,rates,how="left",on="Date")
rates['Currency'] = 'USD'
rates['Rate'] = rates['Rate'].ffill()           

     Date   Rate    Currency
0   2017-07-05  1.1329  USD
1   2017-07-06  1.1385  USD
2   2017-07-07  1.1412  USD
3   2017-07-08  1.1412  USD
4   2017-07-09  1.1412  USD
5   2017-07-10  1.1387  USD
6   2017-07-11  1.1405  USD
7   2017-07-12  1.1449  USD
然后进行左连接将得到:

result = pd.merge(sales,rates,how="left",on=["Currency","Date"])
result['Rate'] = np.where(result['Currency'] == 'EUR', 1, result['Rate_y'])
result = result.drop(['Rate_x','Rate_y'],axis =1)
     Date         From      Currency    Amount  Rate
0   2017-07-06  PayPal           USD    100 1.1385
1   2017-07-06  Fastspring       USD    200 1.1385
2   2017-07-09  Fastspring       USD    100 1.1412
3   2017-07-10  EU               EUR    100 1.0000
4   2017-07-10  PayPal           USD    200 1.1387
将提供:

result = pd.merge(sales,rates,how="left",on=["Currency","Date"])
result['Rate'] = np.where(result['Currency'] == 'EUR', 1, result['Rate_y'])
result = result.drop(['Rate_x','Rate_y'],axis =1)
     Date         From      Currency    Amount  Rate
0   2017-07-06  PayPal           USD    100 1.1385
1   2017-07-06  Fastspring       USD    200 1.1385
2   2017-07-09  Fastspring       USD    100 1.1412
3   2017-07-10  EU               EUR    100 1.0000
4   2017-07-10  PayPal           USD    200 1.1387

您可以更改费率数据框以包含所有日期,然后向前填充,在费率数据框中创建一个名为“货币”的列,然后在日期和货币列上加入两个df

idx = pd.DataFrame(pd.date_range('2017-07-05', '2017-07-12'),columns=['Date'])
rates = pd.merge(idx,rates,how="left",on="Date")
rates['Currency'] = 'USD'
rates['Rate'] = rates['Rate'].ffill()           

     Date   Rate    Currency
0   2017-07-05  1.1329  USD
1   2017-07-06  1.1385  USD
2   2017-07-07  1.1412  USD
3   2017-07-08  1.1412  USD
4   2017-07-09  1.1412  USD
5   2017-07-10  1.1387  USD
6   2017-07-11  1.1405  USD
7   2017-07-12  1.1449  USD
然后进行左连接将得到:

result = pd.merge(sales,rates,how="left",on=["Currency","Date"])
result['Rate'] = np.where(result['Currency'] == 'EUR', 1, result['Rate_y'])
result = result.drop(['Rate_x','Rate_y'],axis =1)
     Date         From      Currency    Amount  Rate
0   2017-07-06  PayPal           USD    100 1.1385
1   2017-07-06  Fastspring       USD    200 1.1385
2   2017-07-09  Fastspring       USD    100 1.1412
3   2017-07-10  EU               EUR    100 1.0000
4   2017-07-10  PayPal           USD    200 1.1387
将提供:

result = pd.merge(sales,rates,how="left",on=["Currency","Date"])
result['Rate'] = np.where(result['Currency'] == 'EUR', 1, result['Rate_y'])
result = result.drop(['Rate_x','Rate_y'],axis =1)
     Date         From      Currency    Amount  Rate
0   2017-07-06  PayPal           USD    100 1.1385
1   2017-07-06  Fastspring       USD    200 1.1385
2   2017-07-09  Fastspring       USD    100 1.1412
3   2017-07-10  EU               EUR    100 1.0000
4   2017-07-10  PayPal           USD    200 1.1387

我使用pd.merge\u asof分解这些步骤

然后


我使用pd.merge\u asof分解这些步骤

然后


下面是我在没有合并的情况下如何做到这一点。 1.用缺失的日期填写费率,用其他答案填写ffill,但保留日期作为索引。 2.将此数据框映射到sales,使用loc不包括带有EUR的行

idx = pd.date_range(rates['Date'].min(), rates['Date'].max())
rates = rates.set_index('Date').reindex(idx).ffill()
sales.loc[sales['Currency'] != 'EUR','Rate'] = sales.loc[sales['Currency'] != 'EUR','Date'].map(rates['Rate'])

    Date        From        Currency    Amount  Rate
0   2017-07-06  PayPal      USD         100     1.1385
1   2017-07-06  Fastspring  USD         200     1.1385
2   2017-07-09  Fastspring  USD         100     1.1412
3   2017-07-10  EU          EUR         100     1.0000
4   2017-07-10  PayPal      USD         200     1.1387
或者您甚至可以在不更改数据帧速率的情况下执行此操作

mapper = rates.set_index('Date').reindex(sales['Date'].unique()).ffill()['Rate']

sales.loc[sales['Currency'] != 'EUR','Rate'] = sales.loc[sales['Currency'] != 'EUR','Date'].map(mapper)
时间测试:

wen:       0.011892538983374834
gayatri:   0.13312408898491412
vaishali : 0.009498710976913571

下面是我在没有合并的情况下如何做到这一点。 1.用缺失的日期填写费率,用其他答案填写ffill,但保留日期作为索引。 2.将此数据框映射到sales,使用loc不包括带有EUR的行

idx = pd.date_range(rates['Date'].min(), rates['Date'].max())
rates = rates.set_index('Date').reindex(idx).ffill()
sales.loc[sales['Currency'] != 'EUR','Rate'] = sales.loc[sales['Currency'] != 'EUR','Date'].map(rates['Rate'])

    Date        From        Currency    Amount  Rate
0   2017-07-06  PayPal      USD         100     1.1385
1   2017-07-06  Fastspring  USD         200     1.1385
2   2017-07-09  Fastspring  USD         100     1.1412
3   2017-07-10  EU          EUR         100     1.0000
4   2017-07-10  PayPal      USD         200     1.1387
或者您甚至可以在不更改数据帧速率的情况下执行此操作

mapper = rates.set_index('Date').reindex(sales['Date'].unique()).ffill()['Rate']

sales.loc[sales['Currency'] != 'EUR','Rate'] = sales.loc[sales['Currency'] != 'EUR','Date'].map(mapper)
时间测试:

wen:       0.011892538983374834
gayatri:   0.13312408898491412
vaishali : 0.009498710976913571

这是向前迈出的一大步,谢谢!它仍然将NaN保留在第2行,而在本例中,它应该使用rates['Rate'][2]是的,谢谢–我已经看到了修改后的答案谢谢。巧妙的技巧,填上遗漏的日期,然后说这是一个很好的进步,谢谢!它仍然将NaN保留在第2行,而在本例中,它应该使用rates['Rate'][2]是的,谢谢–我已经看到了修改后的答案谢谢。巧妙的技巧,填上遗漏的日期,然后这真是太棒了@Gayatri注意到你的回答也很好:@DavideBarranca yw:-)这太棒了@Gayatri注意到你的回答也很好:@DavideBarranca yw:-)