在电商数据分析工作中,经常需要统计不同价格商品的顾客平均购买价格,比如某平台有1000种不同定价的商品,每种商品对应不同的购买人次,需要计算所有顾客的平均支付价格。如果使用Python原生循环处理,面对十万甚至百万级的数据量时效率会非常低,而NumPy的向量化运算可以完美解决这个问题。

传统循环方式的计算逻辑
传统方式需要先遍历每种商品的价格和购买人次,计算总支付金额和总购买人次,最后做除法得到平均价格。示例代码如下:
# 商品价格列表,单位:元
prices = [19.9, 29.9, 39.9, 49.9, 59.9]
# 对应商品的购买人次
counts = [120, 85, 60, 40, 30]
total_amount = 0
total_count = 0
for price, count in zip(prices, counts):
total_amount += price * count
total_count += count
avg_price = total_amount / total_count
print(f"平均购买价格:{avg_price:.2f}元")
这种方式在数据量较小时没有问题,但当商品数量达到10万以上时,循环的执行速度会明显下降,因为Python的循环是解释执行的,没有底层优化。
NumPy向量化计算实现
NumPy的核心是ndarray数组,所有运算都是向量化的,不需要显式编写循环,底层由C语言实现,运算速度比原生Python快很多。我们可以用NumPy重写上面的计算逻辑:
import numpy as np
# 将列表转换为NumPy数组
prices_arr = np.array([19.9, 29.9, 39.9, 49.9, 59.9])
counts_arr = np.array([120, 85, 60, 40, 30])
# 向量化计算总支付金额和总购买人次
total_amount = np.sum(prices_arr * counts_arr)
total_count = np.sum(counts_arr)
avg_price = total_amount / total_count
print(f"平均购买价格:{avg_price:.2f}元")
这里prices_arr * counts_arr会直接对两个数组的对应元素做乘法,生成每个商品的总支付金额数组,再用np.sum求和,整个过程没有显式循环,效率提升非常明显。
两种方式的性能对比
我们通过生成10万条商品数据来对比两种方式的执行时间:
import numpy as np
import time
# 生成10万条随机商品价格(10-100元之间)和购买人次(1-200之间)
np.random.seed(42)
prices = np.random.uniform(10, 100, 100000)
counts = np.random.randint(1, 200, 100000)
# 传统循环方式计时
start = time.time()
total_amount = 0
total_count = 0
for price, count in zip(prices, counts):
total_amount += price * count
total_count += count
avg_price1 = total_amount / total_count
loop_time = time.time() - start
# NumPy向量化方式计时
start = time.time()
prices_arr = np.array(prices)
counts_arr = np.array(counts)
total_amount = np.sum(prices_arr * counts_arr)
total_count = np.sum(counts_arr)
avg_price2 = total_amount / total_count
numpy_time = time.time() - start
print(f"传统循环耗时:{loop_time:.4f}秒")
print(f"NumPy计算耗时:{numpy_time:.4f}秒")
print(f"两种方式结果是否一致:{abs(avg_price1 - avg_price2) < 1e-6}")
实际运行后可以看到,传统循环方式耗时通常在几秒甚至十几秒,而NumPy方式耗时基本在毫秒级别,性能差距可以达到几十倍甚至上百倍。
处理带权重的复杂场景
如果还需要考虑不同顾客的权重,比如老顾客的购买权重是1.2,新顾客是1.0,也可以直接用NumPy扩展计算逻辑:
import numpy as np
prices_arr = np.array([19.9, 29.9, 39.9, 49.9, 59.9])
counts_arr = np.array([120, 85, 60, 40, 30])
# 对应商品的顾客权重,老顾客多的商品权重更高
weights = np.array([1.2, 1.1, 1.0, 1.0, 0.9])
# 加权总支付金额
weighted_total = np.sum(prices_arr * counts_arr * weights)
# 加权总购买人次
weighted_count = np.sum(counts_arr * weights)
weighted_avg = weighted_total / weighted_count
print(f"加权平均购买价格:{weighted_avg:.2f}元")
这种场景下NumPy的向量化运算依然可以轻松应对,不需要修改整体逻辑,只需要在计算时加入权重数组即可。
注意事项
- 使用NumPy前需要确保已经安装库,可以通过
pip install numpy命令安装 - 数组运算时要保证价格和购买人次的数组长度一致,否则会报维度不匹配的错误
- 如果数据量特别大,可以考虑使用NumPy的
float32类型存储数据,进一步减少内存占用