如何根据 Pandas 数据框中的两行加快分数计算?
How do you speed up a score calculation based on two rows in a Pandas Dataframe?
TLDR:如何调整 for 循环以获得更快的执行时间:
import numpy as np
import pandas as pd
import time
np.random.seed(0)
# Given a DataFrame df and a row_index
df = pd.DataFrame(np.random.randint(0, 3, size=(30000, 50)))
target_row_index = 5
start = time.time()
target_row = df.loc[target_row_index]
result = []
# Method 1: Optimize this for-loop
for row in df.iterrows():
"""
Logic of calculating the variables check and score:
if the values for a specific column are 2 for both rows (row/target_row), it should add 1 to the score
if for one of the rows the value is 1 and for the other 2 for a specific column, it should subtract 1 from the score.
"""
check = row[1]+target_row # row[1] takes 30 microseconds per call
score = np.sum(check == 4) - np.sum(check == 3) # np.sum takes 47 microseconds per call
result.append(score)
print(time.time()-start)
# Goal: Calculate the list result as efficient as possible
# Method 2: Optimize Apply
def add(a, b):
check = a + b
return np.sum(check == 4) - np.sum(check == 3)
start = time.time()
q = df.apply(lambda row : add(row, target_row), axis = 1)
print(time.time()-start)
所以我有一个大小为 30'000 的数据框和一个具有给定行索引的目标行。现在我想通过计算分数将这一行与数据集中的所有其他行进行比较。分数计算如下:
- 如果特定列的值对于两行都是 2,则应该将分数加 1
- 如果其中一行的值为 1,而对于特定列的其他 2 行,则应从分数中减去 1。
结果就是我们刚刚计算的所有分数的列表。
因为我需要经常执行这段代码,所以我想优化它以提高性能。
非常感谢任何帮助。
我已经阅读了Optimization when using Pandas您是否可以推荐更多资源?谢谢
如果您愿意将 df
转换为 NumPy
数组,NumPy
有一些非常好的矢量化可以提供帮助。我使用 NumPy
的代码如下:
df = pd.DataFrame(np.random.randint(0, 3, size=(30000, 50)))
target_row_index = 5
start_time = time.time()
# Converting stuff to NumPy arrays
target_row = df.loc[target_row_index].to_numpy()
np_arr = df.to_numpy()
# Calculations
np_arr += target_row
check = np.sum(np_arr == 4, axis=1) - np.sum(np_arr == 3, axis=1)
result = list(check)
end_time = time.time()
print(end_time - start_time)
你的完整代码(对我来说在 Google Colab 上)输出时间 14.875332832336426 s
,而上面的 NumPy
代码输出时间 0.018691539764404297 s
,并且当然,result
列表在两种情况下都是相同的。
请注意,一般来说,如果您的计算是纯数值的,NumPy
实际上总是比 Pandas
和 for
循环更好。 Pandas
真的很适合字符串,当你需要列名和行名时,但是对于纯数字,NumPy
是由于矢量化的方式。
TLDR:如何调整 for 循环以获得更快的执行时间:
import numpy as np
import pandas as pd
import time
np.random.seed(0)
# Given a DataFrame df and a row_index
df = pd.DataFrame(np.random.randint(0, 3, size=(30000, 50)))
target_row_index = 5
start = time.time()
target_row = df.loc[target_row_index]
result = []
# Method 1: Optimize this for-loop
for row in df.iterrows():
"""
Logic of calculating the variables check and score:
if the values for a specific column are 2 for both rows (row/target_row), it should add 1 to the score
if for one of the rows the value is 1 and for the other 2 for a specific column, it should subtract 1 from the score.
"""
check = row[1]+target_row # row[1] takes 30 microseconds per call
score = np.sum(check == 4) - np.sum(check == 3) # np.sum takes 47 microseconds per call
result.append(score)
print(time.time()-start)
# Goal: Calculate the list result as efficient as possible
# Method 2: Optimize Apply
def add(a, b):
check = a + b
return np.sum(check == 4) - np.sum(check == 3)
start = time.time()
q = df.apply(lambda row : add(row, target_row), axis = 1)
print(time.time()-start)
所以我有一个大小为 30'000 的数据框和一个具有给定行索引的目标行。现在我想通过计算分数将这一行与数据集中的所有其他行进行比较。分数计算如下:
- 如果特定列的值对于两行都是 2,则应该将分数加 1
- 如果其中一行的值为 1,而对于特定列的其他 2 行,则应从分数中减去 1。
结果就是我们刚刚计算的所有分数的列表。
因为我需要经常执行这段代码,所以我想优化它以提高性能。 非常感谢任何帮助。
我已经阅读了Optimization when using Pandas您是否可以推荐更多资源?谢谢
如果您愿意将 df
转换为 NumPy
数组,NumPy
有一些非常好的矢量化可以提供帮助。我使用 NumPy
的代码如下:
df = pd.DataFrame(np.random.randint(0, 3, size=(30000, 50)))
target_row_index = 5
start_time = time.time()
# Converting stuff to NumPy arrays
target_row = df.loc[target_row_index].to_numpy()
np_arr = df.to_numpy()
# Calculations
np_arr += target_row
check = np.sum(np_arr == 4, axis=1) - np.sum(np_arr == 3, axis=1)
result = list(check)
end_time = time.time()
print(end_time - start_time)
你的完整代码(对我来说在 Google Colab 上)输出时间 14.875332832336426 s
,而上面的 NumPy
代码输出时间 0.018691539764404297 s
,并且当然,result
列表在两种情况下都是相同的。
请注意,一般来说,如果您的计算是纯数值的,NumPy
实际上总是比 Pandas
和 for
循环更好。 Pandas
真的很适合字符串,当你需要列名和行名时,但是对于纯数字,NumPy
是由于矢量化的方式。