老码农和你一起学AI:Python系列-Pandas 向量化操作

在数据处理的日常工作中,Pandas 凭借其强大的功能成为了众多从业者的首选工具。而在 Pandas 的使用中,向量化操作是提升效率的关键,它能让我们摆脱循环的束缚,轻松应对大规模数据集。今天就让我们结合具体 Python 代码,详细梳理下 Pandas 向量化操作取代循环的相关技巧。

一、循环在 Pandas 数据处理中的局限

在 Pandas 中,使用循环处理数据往往会让效率大打折扣。我们通过代码直观感受循环与向量化操作的效率差距。

首先创建一个包含 10 万行数据的测试 DataFrame:


import pandas as pd

import numpy as np

# 生成测试数据

np.random.seed(42)

df = pd.DataFrame({

'col1': np.random.randint(0, 100, size=100000),

'col2': np.random.randint(0, 100, size=100000)

})

1、循环处理两列相加(低效)


# 循环遍历行计算两列之和

result_loop = []

for index, row in df.iterrows():

result_loop.append(row['col1'] + row['col2'])

df['sum_loop'] = result_loop

2、向量化操作两列相加(高效)


# 向量化操作计算两列之和

df['sum_vectorized'] = df['col1'] + df['col2']

通过%timeit测试可发现:循环方式处理 10 万行数据需要约 10 秒,而向量化操作仅需 0.005 秒,效率差距高达 2000 倍。这是因为循环需要逐行读取数据并转换为 Python 对象,而向量化操作直接对底层数组执行批量计算。

二、Pandas 向量化操作的优势及原理

Pandas 向量化操作的核心优势是直接操作底层数组,我们可以通过代码验证其执行逻辑:


# 查看Series底层数组

print(type(df['col1'].values)) # 输出:<class 'numpy.ndarray'>

# 向量化操作本质是对NumPy数组的批量运算

array_sum = df['col1'].values + df['col2'].values

df['sum_array'] = array_sum # 与df['col1'] + df['col2']结果完全一致

这段代码证明:Pandas 的列运算本质是对 NumPy 数组的操作,绕过了 Python 循环的解释器开销。底层 C 语言实现的数组运算,能充分利用 CPU 缓存和并行计算能力,这也是效率提升的核心原因。

三、Pandas 中替代循环的向量化操作函数及使用技巧

1.、直接利用运算符的向量化操作

适用于算术运算、比较运算等基础操作,代码简洁且效率最高。


# 算术运算:两列相乘

df['product'] = df['col1'] * df['col2']

# 比较运算:判断col1是否大于col2

df['col1_larger'] = df['col1'] > df['col2']

# 复合运算:(col1 + col2)的平方

df['sum_squared'] = (df['col1'] + df['col2']) **2

2. 条件判断:用np.where()替代循环if-else

当需要根据条件赋值时,np.where()比循环判断更高效。


# 需求:col1>50则col3=col1*2,否则col3=col1/2

# 向量化实现

df['col3_vector'] = np.where(df['col1'] > 50, df['col1']*2, df['col1']/2)

# 循环实现(低效,仅作对比)

col3_loop = []

for _, row in df.iterrows():

if row['col1'] > 50:

col3_loop.append(row['col1']*2)

else:

col3_loop.append(row['col1']/2)

df['col3_loop'] = col3_loop

测试表明:np.where()处理 10 万行数据耗时约 0.01 秒,而循环需要 8 秒以上。

3. df.apply()的合理使用

当需要自定义复杂逻辑时,优先用apply()按列操作(避免按行)。


# 需求:计算col1的平方加上col2的平方根

# 自定义函数

def custom_calc(col):

return col['col1']** 2 + np.sqrt(col['col2'])

# 按行apply(效率较低,不推荐)

df['custom_row'] = df.apply(custom_calc, axis=1)

# 优化:拆分为按列运算(效率提升5-10倍)

df['custom_col'] = df['col1'] **2 + np.sqrt(df['col2'])

注意:能拆分为列运算的逻辑,尽量避免用apply(axis=1)。apply的本质是对每个元素调用 Python 函数,效率低于纯向量化操作。

4. 避免使用iterrows():用itertuples()作为临时替代

若必须遍历(如调用外部 API),itertuples()比iterrows()效率高 3-5 倍。


# 高效遍历替代方案(仍不推荐,仅用于无法向量化的场景)

result = []

for row in df.itertuples(index=False): # 返回命名元组,比Series转换更快

result.append(row.col1 + row.col2)

df['itertuples_sum'] = result

四、培养 Pandas 向量化思维的实战技巧

1. 用内置方法替代循环聚合

Pandas 内置的sum()、mean()等方法均为向量化实现。


# 替代:循环计算col1的平均值

# 向量化实现

col1_mean = df['col1'].mean()

# 按条件聚合:col1>50的行的col2总和

sum_large = df[df['col1'] > 50]['col2'].sum()

2. 用索引操作替代循环修改

通过loc条件索引,可批量修改数据,替代循环逐行赋值。


# 需求:col1>50的行,col4赋值为"high",否则为"low"

# 向量化实现

df.loc[df['col1'] > 50, 'col4'] = 'high'

df.loc[df['col1'] <= 50, 'col4'] = 'low'

3. 分组操作:groupby()替代 "循环分组 + 聚合"

对分组数据进行统计时,groupby()的聚合操作是向量化的。


# 需求:按col4分组,计算每组col1的平均值

# 向量化实现

group_mean = df.groupby('col4')['col1'].mean()

print(group_mean)

# 输出:

# col4

# high 74.6

# low 25.3

# Name: col1, dtype: float64

4. 用%timeit测试效率

通过实际测试感受效率差距,强化向量化思维。


# 测试循环vs向量化的效率

%timeit df.apply(lambda x: x['col1'] + x['col2'], axis=1) # 循环思维,约500ms

%timeit df['col1'] + df['col2'] # 向量化,约1ms(效率提升500倍)

最后小结

通过代码示例可以清晰看到:Pandas 向量化操作的核心是用 “列级操作” 替代 “行级循环”。无论是基础运算还是复杂逻辑,向量化代码不仅更简洁,还能借助底层优化实现百倍级效率提升。

实际使用时,建议先思考:“能否对整个列执行操作?” 而非 “如何遍历每个元素?”。向量化思维形成是关键,那么你数据处理效率也会显著提升。未完待续..........

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值