我试图避免for循环在熊猫df的每行基础上应用函数。我看过许多矢量化示例,但没有发现任何可以完全起作用的示例。最终,我试图添加一个额外的df列,其中包含成功条件的总和,并按行为每个条件指定一个指定值。
我看过np.apply_along_axis,但这只是一个隐藏的循环,在np.where,但是我看不到它在我正在检查的25种情况下起作用
A B C ... R S T
0 0.279610 0.307119 0.553411 ... 0.897890 0.757151 0.735718
1 0.718537 0.974766 0.040607 ... 0.470836 0.103732 0.322093
2 0.222187 0.130348 0.894208 ... 0.480049 0.348090 0.844101
3 0.834743 0.473529 0.031600 ... 0.049258 0.594022 0.562006
4 0.087919 0.044066 0.936441 ... 0.259909 0.979909 0.403292
[5 rows x 20 columns]
def point_calc(row):
points = 0
if row[2] >= row[13]:
points += 1
if row[2] < 0:
points -= 3
if row[4] >= row[8]:
points += 2
if row[4] < row[12]:
points += 1
if row[16] == row[18]:
points += 4
return points
points_list = []
for indx, row in df.iterrows():
value = point_calc(row)
points_list.append(value)
df['points'] = points_list
这显然效率不高,但是我不确定如何对代码进行矢量化,因为它需要df中每一列的每行值来获得条件的自定义总和。
任何帮助我指出正确方向的帮助都将不胜感激。
谢谢。
更新: 我可以用df.apply替换df.iterrows部分,从而获得更高的速度。
df['points'] = df.apply(lambda row: point_calc(row), axis=1)
UPDATE2: 我对函数进行了如下更新,并且与使用df.apply和初始函数相比,运行时间大大减少,速度提高了10倍。
def point_calc(row):
a1 = np.where(row[:,2]) >= row[:,13], 1,0)
a2 = np.where(row[:,2] < 0, -3, 0)
a3 = np.where(row[:,4] >= row[:,8])
etc.
all_points = a1 + a2 + a3 + etc.
return all_points
df['points'] = point_calc(df.to_numpy())
我仍在研究的是在函数本身上使用np.vectorize,以查看是否也可以改进。
答案 0 :(得分:1)
您可以通过以下方式尝试:
# this is a small version of your dataframe
df = pd.DataFrame(np.random.random((10,4)), columns=list('ABCD'))
看起来像这样:
A B C D
0 0.724198 0.444924 0.554168 0.368286
1 0.512431 0.633557 0.571369 0.812635
2 0.680520 0.666035 0.946170 0.652588
3 0.467660 0.277428 0.964336 0.751566
4 0.762783 0.685524 0.294148 0.515455
5 0.588832 0.276401 0.336392 0.997571
6 0.652105 0.072181 0.426501 0.755760
7 0.238815 0.620558 0.309208 0.427332
8 0.740555 0.566231 0.114300 0.353880
9 0.664978 0.711948 0.929396 0.014719
您可以创建一个计算点数并用零初始化的系列:
points = pd.Series(0, index=df.index)
看起来像这样:
0 0
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 0
dtype: int64
之后,如果需要,可以逐行添加和减去值:
括号内的条件选择条件为true的行。
因此,-=
和+=
仅适用于那些行。
points.loc[df.A < df.C] += 1
points.loc[df.B < 0] -= 3
最后,您可以根据需要将序列的值提取为numpy数组(可选):
point_list = points.values
这可以解决您的问题吗?