我发现自己失去了试图解决这个问题(自动化税务文书工作)。我有两个数据框:一个是欧元/美元汇率的季度历史记录,另一个是我自己的发票,例如:
import pandas as pd
import numpy as np
usdeur = [(pd.Timestamp('20170705'),1.1329),
(pd.Timestamp('20170706'),1.1385),
(pd.Timestamp('20170707'),1.1412),
(pd.Timestamp('20170710'),1.1387),
(pd.Timestamp('20170711'),1.1405),
(pd.Timestamp('20170712'),1.1449)]
labels = ['Date', 'Rate']
rates = pd.DataFrame.from_records(usdeur, columns=labels)
transactions = [(pd.Timestamp('20170706'), 'PayPal', 'USD', 100, 1),
(pd.Timestamp('20170706'), 'Fastspring', 'USD', 200, 1),
(pd.Timestamp('20170709'), 'Fastspring', 'USD', 100, 1),
(pd.Timestamp('20170710'), 'EU', 'EUR', 100, 1),
(pd.Timestamp('20170710'), 'PayPal', 'USD', 200, 1)]
labels = ['Date', 'From', 'Currency', 'Amount', 'Rate']
sales =pd.DataFrame.from_records(transactions, columns=labels)
导致:
我需要让sales['Rate']
列填充rates['Rate']
的正确汇率,也就是说:
sales['Currency']
为'EUR'
,请不要理会。 li>
sales
的每一行,找到rates
中匹配'Date'
的行;获取rates['Rate']
非常sales['Rate']
值并将其放入'Date'
Question:
var Question = sequelize.define('Question', {
}, {
classMethods: {
associate: function (models) {
// associations can be defined here
Question.belongsTo(models.User, {
as: 'askerId',
foreignKey: 'askerId'
})
Question.belongsTo(models.User, {
as: 'winnerId',
foreignKey: 'winnerId'
})
Question.hasMany(models.Suggestion)
Question.hasMany(models.TagQuestion)
}
}
})
(例如在假日期间,交易所市场已关闭),请检查上一行,直至找到合适的值。完整结果应如下所示(请注意第2行的比率为2017-07-07):
我试图从其他问题中遵循几个建议的解决方案,但没有运气。 非常感谢您提前
答案 0 :(得分:2)
您可以更改费率数据框以包含所有日期,然后转发填充,在费率数据框中创建一个名为“货币”的列,然后在日期和时间加入两个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
答案 1 :(得分:2)
我使用pd.merge_asof
sales=pd.merge_asof(sales,rates,on='Date',direction='backward',allow_exact_matches =True)
sales.loc[sales.From=='EU','Rate_y']=sales.Rate_x
sales
Out[748]:
Date From Currency Amount Rate_x Rate_y
0 2017-07-06 PayPal USD 100 1 1.1385
1 2017-07-06 Fastspring USD 200 1 1.1385
2 2017-07-09 Fastspring USD 100 1 1.1412
3 2017-07-10 EU EUR 100 1 1.0000
4 2017-07-10 PayPal USD 200 1 1.1387
然后
sales.drop('Rate_x',1).rename(columns={'Rate_y':'Rate'})
Out[749]:
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
答案 2 :(得分:1)
这是我如何在没有合并的情况下做到这一点。 1.与其他答案一样填写缺少日期和填充的费率,但将日期保留为索引。 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)
Timetesting:
wen: 0.011892538983374834
gayatri: 0.13312408898491412
vaishali : 0.009498710976913571