[英]Conditionally fill column values based on another columns value in pandas
[英]Conditionally fill column with value from another DataFrame based on row match in Pandas
我發現自己迷失了解決這個問題的方法(自動完成稅務文書工作)。 我有兩個數據框:例如,一個具有歐元/美元匯率的季度歷史記錄,另一個具有我自己的發票,例如:
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'
,請不要理會。 sales
,請找到與'Date'
匹配'Date'
rates
行; 抓住非常高的rates['Rate']
價值,然后將其放入sales['Rate']
'Date'
(例如,在假期期間,交易所市場關閉),請檢查上一行直到找到合適的值。 完整結果應如下所示(請注意,第2行的費率自2017年7月7日開始):
我嘗試從其他問題中遵循一些建議的解決方案,但是沒有運氣。 提前非常感謝你
您可以更改費率數據框以包括所有日期,然后向前填充,在費率數據框中創建一個名為“貨幣”的列,然后在日期和貨幣列上將兩個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
我通過使用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
這是我不合並的情況。 1.用缺少的日期填寫費率,並像其他答案一樣填寫,但將日期保留為索引。 2.將此數據框映射到銷售,使用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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.