[英]How to sort each row of pandas dataframe and return column index based on sorted values of row
[英]How to Eliminate for loop in Pandas Dataframe in filling each row values of a column based on multiple if,elif statements
尝试摆脱 for 循环,以根据涉及多列和多行的 if、elif 条件加速填充“C”列中的值的执行。 无法找到合适的解决方案。
尝试将 np.where 与条件、选择和默认值一起应用。 但未能获得预期结果,因为我无法从 pandas 系列 object 中提取单个值。
df = pd.DataFrame()
df['A']=['Yes','Yes','No','No','Yes','No','Yes','Yes','Yes','Yes']
df['B']=[1,1,0,1,1,0,1,0,0,1]
df['C']=None
df['D']=['xyz','Yes','No','xyz','Yes','No','xyz','Yes','Yes','Yes']
df['C'][0]='xyz'
for i in range(0,len(df)-1):
if (df.iloc[1+i, 1]==1) & (df.iloc[i, 2]=="xyz") & (df.iloc[1+i, 0]=="No"):
df.iloc[1+i, 2] = "Minus"
elif (df.iloc[1+i, 1]==1) & (df.iloc[i, 2]=="xyz") & (df.iloc[1+i, 0]=="Yes"):
df.iloc[1+i, 2] = "Plus"
elif (df.iloc[i, 3]!="xyz") or ((df.iloc[1+i, 1]==0) & (df.iloc[i, 2]=="xyz")):
df.iloc[1+i, 2] = "xyz"
elif (df.iloc[1+i, 0]=="Yes") & (df.iloc[i, 2]=="xyz"):
df.iloc[1+i, 2] = "Plus"
elif (df.iloc[1+i, 0]=="No") & (df.iloc[i, 2]=="xyz"):
df.iloc[1+i, 2] = "Minus"
else:
df.iloc[1+i, 2] = df.iloc[i, 2]
df
期待社区的帮助,将上述代码修改为执行时间更短的更好的代码。 最好使用 numpy 矢量化。
循环当然不能使用 Numpy 或 Pandas 进行有效矢量化,因为循环携带数据依赖于df['C']
。 由于 Pandas 直接索引和字符串比较,循环非常慢。 希望您可以使用Numba有效地解决这个问题。 您首先需要将列转换为强类型Numpy arrays 以便 Numba 有用。 请注意,Numba 处理字符串的速度非常慢,因此最好直接使用 Numpy 执行矢量化检查。
这是结果代码:
import numpy as np
import numba as nb
@nb.njit('UnicodeCharSeq(8)[:](bool_[:], int64[:], bool_[:])')
def compute(a, b, d):
n = a.size
c = np.empty(n, dtype='U8')
c[0] = 'xyz'
for i in range(0, n-1):
prev_is_xyz = c[i] == 'xyz'
if b[i+1]==1 and prev_is_xyz and not a[i+1]:
c[i+1] = 'Minus'
elif b[i+1]==1 and prev_is_xyz and a[i+1]:
c[i+1] = 'Plus'
elif d[i] or (b[i+1]==0 and prev_is_xyz):
c[i+1] = 'xyz'
elif a[i+1] and prev_is_xyz:
c[i+1] = 'Plus'
elif not a[i+1] and prev_is_xyz:
c[i+1] = 'Minus'
else:
c[i+1] = c[i]
return c
# Convert the dataframe columns to fast Numpy arrays and precompute some check
a = df['A'].values.astype('U8') == 'Yes'
b = df['B'].values.astype(np.int64)
d = df['D'].values.astype('U8') != 'xyz'
# Compute the result very quickly with Numba
c = compute(a, b, d)
# Store the result back
df['C'].values[:] = c.astype(object)
这是在我的机器上产生的性能:
Basic Pandas loops: 2510 us
This Numba code: 20 us
因此,Numba 实施速度提高了125 倍。 事实上,大部分时间花在 Numpy 转换代码上,甚至没有花在compute
上。 在大型数据帧上,差距应该更大。
请注意,行df['C'].values[:] = c.astype(object)
比等效表达式df['C'] = c
(大约 16 倍)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.