2 回答

TA貢獻1831條經驗 獲得超4個贊
已經解釋了為什么您對 NA 列的比較沒有返回您期望的結果。
但是,我會以與他不同的方式進行比較。這是一個小片段,應該可以幫助您理解:
# a series of bools, indicating for which index our condition is true
na_gt_1_series = df["NA"] > 1
print(na_gt_1)
# creating a new column based on the values of the NA column
df["na_gt_1"] = na_gt_1_series
print(df)
現在,由于這里的條件相當復雜,我認為使用 pandas 的 apply 函數會更簡單,它沿著 DataFrame 的某個軸應用一個函數。
def get_row_df5(row):
df5 = 0
if row["NA"] > 1:
if row["MULT"] == 1:
if row["NOB"] == 1:
df5 = -A1 * row["NOB"]
else:
df5 = -A2 * row["NOB"] - B * (row["NOA"] - row["NOB"])
elif row["NA"] == 1:
if row["MULT"] == 1:
if row["EX"] == 0 and row["NOB"] == 4 and row["CHARGE"] == 0:
df5 = -A1 * row["NOB"]
elif row["NOB"] != 1 or row["NOB"] == 1 and row["EX"] != 0:
df5 = -C * row["NOB"]
elif row["NOB"] == 1 and row["EX"] == 0:
df5 = -E * row["NOB"]
else:
df5 = -C * row["NOB"] - D * (row["NOA"] - row["NOB"])
return df5
df5_res = df.apply(func=get_row_df5, axis=1)
不幸的是,這種簡單性是有代價的。對于通過復制示例數據制作的 120,000 行 DataFrame,應用解決方案需要約 4 秒,而以下解決方案需要約 40 毫秒(快 100 倍)。
def get_df5_broad(df_in):
na_lt_1 = df_in["NA"] > 1
na_eq_1 = df_in["NA"] == 1
mult_eq_1 = df_in["MULT"] == 1
mult_ne_1 = ~mult_eq_1
res_series = pd.Series(np.zeros(shape=df_in.shape[0]))
res_series.loc[na_lt_1 & mult_eq_1 & (df_in["NOB"] == 1)] = -A1 * df_in["NOB"]
res_series.loc[na_lt_1 & mult_ne_1] = -A2 * df_in["NOB"] - B * (df_in["NOA"] - df_in["NOB"])
res_series.loc[na_eq_1 & mult_eq_1 & (df_in["EX"] == 0) & (df_in["NOB"] == 4) & (df_in["CHARGE"] == 0)] = -A1 * df_in["NOB"]
res_series.loc[na_eq_1 & mult_eq_1 & ((df_in["NOB"] != 1) | ((df_in["NOB"] == 1) & (df_in["EX"] != 0)))] = -C * df_in["NOB"]
res_series.loc[na_eq_1 & mult_eq_1 & (df_in["NOB"] == 1) & (df_in["EX"] == 0)] = -E * df_in["NOB"]
res_series.loc[na_eq_1 & mult_ne_1] = -C * df_in["NOB"] - D * (df_in["NOA"] - df_in["NOB"])
return res_series
最后,下一個方法是兩全其美的方法。它的設計和簡單性與使用 apply 的方法相似,但僅比之前的高性能版本慢 5 倍。
def get_df5_tupe(tupe):
df5 = 0
if tupe.NA > 1:
if tupe.MULT == 1:
if tupe.NOB == 1:
df5 = -A1 * tupe.NOB
else:
df5 = -A2 * tupe.NOB - B * (tupe.NOA - tupe.NOB)
elif tupe.NA == 1:
if tupe.MULT == 1:
if tupe.EX == 0 and tupe.NOB == 4 and tupe.CHARGE == 0:
df5 = -A1 * tupe.NOB
elif tupe.NOB != 1 or tupe.NOB == 1 and tupe.EX != 0:
df5 = -C * tupe.NOB
elif tupe.NOB == 1 and tupe.EX == 0:
df5 = -E * tupe.NOB
else:
df5 = -C * tupe.NOB - D * (tupe.NOA - tupe.NOB)
return df5
def get_df5_iter(df_in):
return pd.Series((get_df5_tupe(curr) for curr in df_in.itertuples(index=False)))
注意:由于 OP 中的邏輯歧義,這些方法并不總是返回正確的答案。一旦正確的布爾表達式可用,我將立即編輯我的解決方案。

TA貢獻1806條經驗 獲得超5個贊
這個塊在這里:
if (df['NA'] > 1).any():
print(True)
elif (df['NA'] == 1).any():
print(False)
將始終打印 True 因為列 'NA' 的值大于 1,因此不會評估第二個 elif。根據您的評論,如果我沒記錯的話,我認為您想遍歷 DataFrame 并評估每個元素。你可以嘗試這樣的事情:
for val in df['NA']:
if val > 1:
print(True)
elif val == 1:
print(False)
這將評估列“NA”的每個元素,對于您的實際用例,您將想知道給定 val 的索引,這可以使用enumerate. 例如:
for (idx, val) in enumerate(df['NA']):
if val > 1:
d5 = -A1 * df['NOB'].iloc[idx]
elif val == 1:
d5 = E * df['NOB'].iloc[idx]
idx是當前元素的索引,您可以使用 訪問該索引處其他列的元素iloc。我希望這會有所幫助,祝你好運。
添加回答
舉報