亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

比較python中單列pandas數據框的值(將perl轉換為python代碼)

比較python中單列pandas數據框的值(將perl轉換為python代碼)

三國紛爭 2022-06-22 18:26:11
我正在嘗試將 perl 代碼轉換為 python,以便將列簡單地乘以一些常量。我創建了一個帶有多列浮點值的 pandas 數據框。這是 components.csv 文件的示例。      NA  MULT   NOA   NOB  CHARGE   EX0    8.0   1.0  24.0  24.0     0.0  1.01    8.0   1.0  24.0  24.0     0.0  1.02    8.0   1.0   6.0   6.0     0.0  1.03   20.0   1.0  18.0  18.0     0.0  1.04   23.0   1.0  21.0  21.0     0.0  1.05   26.0   1.0  24.0  24.0     0.0  1.06   11.0   1.0  13.0  13.0     0.0  0.07   16.0   1.0  19.0  19.0     1.0  0.08    1.0   1.0   4.0   4.0    -1.0  0.09   17.0   1.0  23.0  23.0     0.0  0.010   1.0   1.0   4.0   4.0     0.0  0.011   1.0   1.0   4.0   4.0     0.0  0.0初始參數為:$A1 = 9.3692400791;$A2 = 9.4492960287;$B  = 3.8320915550;$C  = 9.5936653352;$D  = 1.8739215238;$E  = 2.4908584058;預期的輸出是單列(d5):Df5-0.2249-0.2249-0.0562-0.1686-0.1968-0.2249-0.1218-0.1780-0.0384-0.2155-0.0375-0.0375使用以下方法解析數據幀后:pd.set_option('precision', 8)df = pd.read_csv("unscaled_components_delimit.csv", delimiter= ",", header=0)我有多個條件要檢查,例如以下腳本:if (df['NA'] > 1).any():    print(True)elif (df['NA'] == 1).any():    print(False)然而,上面的代碼只打印一個 True 值,即使在標題為 NA 的列中有多個 1.0 值,這意味著它不會傳遞給第二個 elif。我使用了函數 any() ,也許應該使用我目前不知道的另一個函數。因此,有人可能會為此提出解決方案嗎?目標是將列(標題 NA)的每個元素與數字 1(大于或等于)進行比較。然后,對其他列執行一些具有其他條件的操作。我將不勝感激任何幫助或建議。為了更清楚起見,以下代碼包含具有所有必需條件的最終所需代碼:if (df['NA'] > 1).any():    if (df['MULT'] == 1).any():        if ((df['NOB'] != 1).any() or (df['NOB'] ==1).any()):            d5 = -A1*df['NOB']        elif((df['NOB'] == 1).any()):            d5 = -E*df['NOB']    else:        d5 = -A2*df['NOB'] - B*(df['NOA']-df['NOB'])
查看完整描述

2 回答

?
慕容708150

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 中的邏輯歧義,這些方法并不總是返回正確的答案。一旦正確的布爾表達式可用,我將立即編輯我的解決方案。


查看完整回答
反對 回復 2022-06-22
?
忽然笑

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。我希望這會有所幫助,祝你好運。


查看完整回答
反對 回復 2022-06-22
  • 2 回答
  • 0 關注
  • 169 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號