[英]How can I get pandas to adjust my formula based on a specific value in a dataframe?
我有一個如下所示的pandas
數據框:
Emp_ID | Weekly_Hours | Hire_Date | Termination_Date | Salary_Paid | Multiplier | Hourly_Pay
A1 | 35 | 01/01/1990 | 06/04/2020 | 5000 | 0.229961 | 32.85
B2 | 35 | 02/01/2020 | NaN | 10000 | 0.229961 | 65.70
C3 | 30 | 23/03/2020 | NaN | 5800 | 0.229961 | 44.46
乘數是所有員工的靜態數字,計算為 7 / 30.44。 每小時工資的計算方法是將月工資乘以乘數,再除以每周合同工時。
現在我的挑戰是讓 Pandas 識別 Termination Date 字段中的日期,並調整計算。 例如,第一條記錄需要更新,以顯示該員工在 2020 年 6 月 4 日辭職后,實際上在 4 個工作日內通過工資單支付了 5000 美元,而不是整月。 因此,預期的時薪數字為 (5000 / 4 * 7 / 35) = 250。
我可以很容易地編寫計算代碼; 我的努力是在所有四月畢業生(對任何其他月份不感興趣)的新列中添加一列來反映工作日(上例中的 4 天)。 到目前為止我已經嘗試過了。
df['T_Mth_Workdays'] = np.where(df['Termination_Date'].notnull(), np.busday_count('2020-04-01', df['Termination_Date']), 0)
但是,上述方法返回一個錯誤,指出:
iterator operand 0 dtype could not be cast from dtype(' m8 [ns] ') to dtype(' m8 [d] ')
我應該在這里補充一點,我必須手動將日期更改為 datetime[ns64] 格式。
任何指點,感激地收到。 謝謝!
您的np.where
函數調用的問題在於它試圖將整個系列df["Termination_Date"]
作為參數傳遞給np.busday_count
。 count 函數失敗,因為它要求參數采用np.datetime64[D]
格式(即,僅指定到當天的值),並且系列無法輕松轉換為這種格式。
一種解決方案是編寫自定義功能,只有調用np.busday_count
在不是元素NaT
S,變換的那些到datetime64[D]
之前調用類型np.busday_count
。 然后,您可以apply
自定義函數應用於df["Termination_Date"]
系列,如下所示:
#!/usr/bin/env python3
import numpy as np
import pandas as pd
DATE_FORMAT = "%d-%m-%Y"
# Reproduce raw data
raw_data = [
["A1", 35, "01/01/1990", "06/04/2020", 5000, 0.229961, 32.85],
["B2", 35, "02/01/2020", None, 10000, 0.229961, 65.70],
["C3", 35, "23/03/2020", "NAT", 5800, 0.229961, 44.46],
]
# Convert raw dates to ISO format, then np.datetime64
def parse_raw_dates(s):
try:
spl = s.split("/")
ds = "%s-%s-%s" %(spl[2], spl[1], spl[0])
except:
ds = "NAT"
return np.datetime64(ds)
for line in raw_data:
line[2] = parse_raw_dates(line[2])
# Create dataframe
df = pd.DataFrame(
data = raw_data,
columns = [
"Emp_ID", "Weekly_Hours", "Hire_Date", "Termination_Date",
"Salary_Paid", "Multiplier", "Hourly_Pay"],
)
# Create special conversion function
def myfunc(d):
d = d.to_numpy().astype('datetime64[D]')
if np.isnat(d):
return 0
else:
return np.busday_count('2020-04-01', d)
df['T_Mth_Workdays'] = df["Termination_Date"].apply(myfunc)
def format_date(d):
d = d.to_numpy().astype('datetime64[D]')
if np.isnat(d):
return ""
else:
return pd.to_datetime(d).strftime(DATE_FORMAT)
df["Hire_Date"] = df["Hire_Date"].apply(format_date)
df["Termination_Date"] = df["Termination_Date"].apply(format_date)
在這里發布我的方法,以防將來對其他人有所幫助。 首先是創建數據框的代碼:
d = {'Emp_ID': ['A1', 'B2', 'C3'], 'Weekly Hours': ['35', '35', '30'], 'Hire_Date': ['01/01/1990', '02/01/2020', '23/03/2020'],
'Termination_Date': ['06/04/2020', np.nan, np.nan], 'Salary_Paid': [5000, 10000, 5800]}
df = pd.DataFrame(data=d)
df
第一步是將日期轉換為更有用的格式——這是pd.to_datetime()
派上用場的地方——需要的調整是指定格式。
df['Hire_Date'] = pd.to_datetime(df['Hire_Date'], format='%d/%m/%Y')
df['Termination_Date'] = pd.to_datetime(df['Termination_Date'], format='%d/%m/%Y')
這具有預期的效果; 從而正確表示日期,並選擇四月作為員工 A1 的正確終止月份。
我現在(稍微)調整了 Ken 用於計算 4 月份工作日的自定義解決方案:
def workday_calc(d):
d = d.to_numpy().astype('datetime64[D]')
if np.isnat(d):
return 30.44
else:
d = d.astype(str)
d = dt.datetime.strptime(d, '%Y-%m-%d')
e = (d + dt.timedelta(1)).strftime('%Y-%m-%d')
return np.busday_count('2020-04-01', e, weekmask=[1,1,1,1,1,0,0])
我在查看np.busday_count()
上的numpy 文檔時發現了錯誤。 有兩個有用的指針需要注意: 在函數的第一行中必須使用datetime64[D]
- 您不能使用pd.to_datetime()
。 這是因為datetime64[D]
格式是能夠調用np.isnat()
函數的先決條件。
但是,在我們處理數據幀中的NaT
那一刻,我們需要切換回字符串格式,這是datetime.strptime()
函數所需要的。 使用datetime.strptime()
特性,我們告訴 Python 日期是 a) 以 ISO 格式表示,我們需要將其保留為字符串。 datetime.strptime()
和np.busday_count()
的優點是它們都是為處理字符串而構建的。
此外, np.busday_count()
不包括結束日期,因此我使用timedelta()
將結束日期加一,以便計算中間的所有日期。 考慮到您要執行的操作,這可能合適也可能不合適,但我想要包含 4 月份工作的天數。 因此,在這種情況下,該員工在 4 月份工作了 4 個工作日。
然后我們只需應用自定義函數並創建一個新列。
df['Days_Worked_April'] = df['Termination_Date'].apply(workday_calc)
我現在可以使用新創建的列來推導我的乘數 - 使用相同的舊方法。 其余的很簡單,但為了完整起見,我在下面包含了代碼和結果。
df['Multiplier'] = df.apply(lambda x: 7 / x['Days_Worked_April'], axis=1)
df['Hourly_Pay_Calc'] = round((df.apply(lambda x: x['Salary_Paid'] * x['Multiplier'] / x['Weekly Hours'], axis=1)), 2)
輸出:
Emp_ID Weekly Hours Hire_Date Termination_Date Salary_Paid Days_Worked_April Multiplier Hourly_Pay_Calc
0 A1 35.0 1990-01-01 2020-04-06 5000 4.00 1.750000 250.00
1 B2 35.0 2020-01-02 NaT 10000 30.44 0.229961 65.70
2 C3 30.0 2020-03-23 NaT 5800 30.44 0.229961 44.46
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.