繁体   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