簡體   English   中英

Pandas - 滿足條件時,將多個列值替換為先前的列值

[英]Pandas - Replace multiple column values with previous column value when condition is met

我有一個大型數據框,如下所示:

Start       End        Alm_No1 Val_No1  Alm_No2 Val_No2 Alm_No3 Val_No3
1/1/19 0:00 1/2/19 0:00    1       0       2       1       3       0
1/2/19 0:00 1/3/19 0:00    1       0       2       0       3       1
1/3/19 0:00 1/4/19 0:00    1       1       2       0       3       0
1/4/19 0:00 1/5/19 0:00    1       0       2       0       3       1
1/5/19 0:00 1/6/19 0:00    1       1       2       0       3       0
1/6/19 0:00 1/7/19 0:00    1       0       2       1       3       1
1/7/19 0:00 1/8/19 0:00    4       0       5       1       6       0
1/8/19 0:00 1/9/19 0:00    4       0       5       1       6       1
1/9/19 0:00 1/10/19 0:00   4       1       5       1       6       0

我想用“Alm”列中的數字更新“Val”列中的所有值(如果值為1),以便我可以刪除“Alm”列。

結果如下:

Start           End     Alm_No1  Val_No1 Alm_No2 Val_No2  Alm_No3 Val_No3
1/1/19 0:00 1/2/19 0:00    1       0       2       2       3       0
1/2/19 0:00 1/3/19 0:00    1       0       2       0       3       3
1/3/19 0:00 1/4/19 0:00    1       1       2       0       3       0
1/4/19 0:00 1/5/19 0:00    1       0       2       0       3       3
1/5/19 0:00 1/6/19 0:00    1       1       2       0       3       0
1/6/19 0:00 1/7/19 0:00    1       0       2       2       3       3
1/7/19 0:00 1/8/19 0:00    4       0       5       5       6       0
1/8/19 0:00 1/9/19 0:00    4       0       5       5       6       6
1/9/19 0:00 1/10/19 0:00   4       4       5       5       6       0

我創建了應該更改值的列的列表:

val_col = df.columns.tolist()
val_list=[]
for i in range(0, len(val_col)) : 
    if val_col[i].startswith('Val'): 
        val_list.append(i)

然后我嘗試創建一段時間來迭代列:

for x in val_list: 
    i = 0 
    while i < len(df): 
        if df.iloc[i, x] == 1: 
            df.iloc[i, x] = df.iloc[i, x-1] 
            i+=1 

它需要永遠的負載,我很難找到適合lambda或適用的東西。 任何提示? 提前致謝!

永遠不要遍歷數據幀的行。 您應該在一個操作中設置所有列。

for i in range(1,4): 
    df[f'Val_No{i}'] *= df[f'Alm_No{i}'] 

幾分鍾后我覺得自己回答自己的問題很傻,但我覺得我發現了一些有用的東西:

for x in val_list:
    df.loc[df.iloc[:,x]==1,df.columns[x]] = df.iloc[:, x-1]

像魅力一樣工作!

234 ms ± 15.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

我想出了一個適用於任意數量的Alm_No ... / Val_No ...列的解決方案。

讓我們從要應用於每一行的函數開始:

def fn(row):
    for i in range(2, row.size, 2):
        j = i + 1
        if row.iloc[j]:
            row.iloc[j] = row.iloc[i]
    return row

注意for循環的結構。 它從2Alm_No1列的位置)開始,步驟2 (到Alm_No2列的距離)。

j保存下一列的編號( Val_No ... )。

如果“當前” Val_No != 0則在此替換“當前” Alm_No中的值。

循環完成后,返回更改的行。

所以唯一要做的就是將這個函數應用於每一行:

df.apply(fn, axis=1)

timeit測量表明,我的解決方案可以運行的小(7%)比你更快,比BallpointBen提出的一個快35倍左右。

顯然,f-strings的使用在這個(非常顯着的)差異中有一些份額。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM