我有一个看起来像这样的大数据框:
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
如果值是1,我想用关联的“ Alm”列中的数字更新“ Val”列中的所有值,这样我就可以摆脱“ 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或应用的东西。有什么提示吗? 预先感谢!
答案 0 :(得分:0)
永远不要在数据框的行上循环。您应该一次完成设置所有列的操作。
for i in range(1,4):
df[f'Val_No{i}'] *= df[f'Alm_No{i}']
答案 1 :(得分:0)
几分钟后,我回答自己的问题很傻,但我认为我发现了一些可行的方法:
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)
答案 2 :(得分:0)
我想出了一个解决方案,该解决方案可以处理任意个 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 循环的构造。从 2 开始
(Alm_No1
列的位置),以及步骤 2 (到
Alm_No2
列)。
j
保留下一列的编号( Val_No ... )。
如果“当前” Val_No != 0,则在此处替换该值 来自“当前” Alm_No 。
循环完成后,返回更改的行。
所以唯一要做的就是将此功能应用于每一行:
df.apply(fn, axis=1)
我的 timeit 测量表明我的解决方案运行了一点 (7%)比您的速度快,并且比那快 35倍 由 BallpointBen 提出。
显然,f字符串的使用在此方面有一定的份额(非常重要) 差异。