本文目录导读:

- 使用 multiprocessing 进行并行处理
- 使用 swifter 库(推荐)
- 使用 pandas groupby 配合并行
- 使用 joblib 进行并行处理
- 使用 Dask 进行大规模并行处理
- 自定义并行循环
- 性能比较和最佳实践
- 注意事项
我来详细介绍几种使用Pandas进行数据并行处理的方法:
使用 multiprocessing 进行并行处理
基础示例:并行处理DataFrame
import pandas as pd
import numpy as np
from multiprocessing import Pool, cpu_count
import time
# 创建示例数据
def create_large_dataset(n_rows=100000):
df = pd.DataFrame({
'id': range(n_rows),
'value1': np.random.randn(n_rows),
'value2': np.random.randn(n_rows),
'category': np.random.choice(['A', 'B', 'C', 'D'], n_rows)
})
return df
# 耗时处理函数
def complex_processing(row):
# 模拟复杂计算
result = np.sin(row['value1']) * np.cos(row['value2']) + np.sqrt(abs(row['value1']))
time.sleep(0.001) # 模拟耗时操作
return result
# 并行处理版本
def parallel_processing(df, n_cores=None):
if n_cores is None:
n_cores = cpu_count() - 1 # 保留一个核心
# 分割DataFrame
df_split = np.array_split(df, n_cores)
# 创建进程池并执行
with Pool(n_cores) as pool:
results = pool.map(complex_process_chunk, df_split)
# 合并结果
return pd.concat(results, axis=0)
def complex_process_chunk(chunk):
# 处理数据块
chunk['processed'] = chunk.apply(complex_processing, axis=1)
return chunk
# 测试性能
def compare_performance():
df = create_large_dataset(5000)
# 串行处理
start = time.time()
result_serial = df.copy()
result_serial['processed'] = result_serial.apply(complex_processing, axis=1)
serial_time = time.time() - start
# 并行处理
start = time.time()
result_parallel = parallel_processing(df)
parallel_time = time.time() - start
print(f"串行处理时间: {serial_time:.2f}秒")
print(f"并行处理时间: {parallel_time:.2f}秒")
print(f"速度提升: {serial_time/parallel_time:.2f}倍")
# 运行对比
compare_performance()
使用 swifter 库(推荐)
import swifter
import pandas as pd
import numpy as np
# 安装: pip install swifter
# 创建数据
df = pd.DataFrame({
'A': np.random.randn(10000),
'B': np.random.randn(10000)
})
# 复杂计算函数
def complex_calculation(x, y):
# 模拟复杂计算
result = 0
for i in range(100):
result += np.sin(x * i) * np.cos(y * i)
return result
# 使用 swifter 自动并行
# swifter 会自动选择串行或并行
df['result'] = df.swifter.apply(
lambda row: complex_calculation(row['A'], row['B']),
axis=1
)
# 也可以指定使用多核
df['result'] = df.swifter.progress_bar(False).apply(
lambda row: complex_calculation(row['A'], row['B']),
axis=1
)
使用 pandas groupby 配合并行
import pandas as pd
import numpy as np
from multiprocessing import Pool
def process_group(group_df):
"""处理每个分组"""
return group_df.groupby('category').agg({
'value1': ['mean', 'std'],
'value2': ['sum', 'count']
})
# 创建数据
df = pd.DataFrame({
'category': np.random.choice(['A', 'B', 'C', 'D', 'E'], 100000),
'value1': np.random.randn(100000),
'value2': np.random.randn(100000),
'value3': np.random.randn(100000)
})
def parallel_groupby(df, group_col, n_cores=None):
"""并行分组处理"""
if n_cores is None:
n_cores = cpu_count() - 1
# 获取唯一值并分割
unique_groups = df[group_col].unique()
group_chunks = np.array_split(unique_groups, n_cores)
def process_combinations(groups):
mask = df[group_col].isin(groups)
subset = df[mask]
return subset.groupby(group_col).agg({
'value1': ['mean', 'std'],
'value2': ['sum', 'count']
})
with Pool(n_cores) as pool:
results = pool.map(process_combinations, group_chunks)
return pd.concat(results)
# 执行并行groupby
result = parallel_groupby(df, 'category')
使用 joblib 进行并行处理
from joblib import Parallel, delayed
import pandas as pd
import numpy as np
# 创建数据
df = pd.DataFrame({
'id': range(1000),
'data': [np.random.randn(1000) for _ in range(1000)]
})
# 处理函数
def process_single(row):
"""处理单行数据"""
data = row['data']
return {
'id': row['id'],
'mean': np.mean(data),
'std': np.std(data),
'skew': pd.Series(data).skew(),
'kurtosis': pd.Series(data).kurtosis()
}
# 并行处理
def parallel_apply_joblib(df_func, n_jobs=-1):
"""使用joblib并行处理"""
results = Parallel(n_jobs=n_jobs)(
delayed(df_func)(row) for _, row in df.iterrows()
)
return pd.DataFrame(results)
# 执行并行处理
result_df = parallel_apply_joblib(process_single)
使用 Dask 进行大规模并行处理
import dask.dataframe as dd
import pandas as pd
import numpy as np
# 创建大规模数据
def create_big_data():
n = 1000000 # 100万行
df = pd.DataFrame({
'x': np.random.randn(n),
'y': np.random.randn(n),
'category': np.random.choice(['A', 'B', 'C'], n)
})
return df
# 复杂计算函数
def complex_operation(df):
"""对DataFrame执行复杂操作"""
df['z'] = df['x'] * df['y'] + np.sin(df['x']) * np.cos(df['y'])
df['result'] = df.groupby('category')['z'].transform('mean')
return df
# Dask并行处理
def dask_parallel_processing():
# 创建Dask DataFrame
ddf = dd.from_pandas(create_big_data(), npartitions=4)
# 执行复杂操作
result = ddf.map_partitions(complex_operation)
# 触发计算
final_result = result.compute()
return final_result
# 执行
result = dask_parallel_processing()
print(result.head())
自定义并行循环
import pandas as pd
import numpy as np
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
class ParallelProcessor:
def __init__(self, n_workers=None):
self.n_workers = n_workers or cpu_count() - 1
def parallel_for(self, df, func, axis=1):
"""通用并行循环"""
if axis == 1:
# 按行并行
chunks = np.array_split(df, self.n_workers)
with ProcessPoolExecutor(max_workers=self.n_workers) as executor:
results = list(executor.map(self._process_chunk, chunks, [func]*len(chunks)))
return pd.concat(results)
else:
# 按列并行
cols = np.array_split(df.columns, self.n_workers)
with ProcessPoolExecutor(max_workers=self.n_workers) as executor:
results = list(executor.map(self._process_columns, [df]*len(cols), cols, [func]*len(cols)))
return pd.concat(results, axis=1)
def _process_chunk(self, chunk, func):
"""处理数据块"""
return chunk.apply(func, axis=1)
def _process_columns(self, df, columns, func):
"""处理列"""
return df[columns].apply(func)
# 使用示例
df = pd.DataFrame(np.random.randn(1000, 10), columns=[f'col_{i}' for i in range(10)])
processor = ParallelProcessor(n_workers=4)
# 按行并行
result_rows = processor.parallel_for(df, lambda x: x.sum())
# 按列并行
result_cols = processor.parallel_for(df, lambda x: x.mean(), axis=0)
性能比较和最佳实践
def performance_benchmark():
"""性能基准测试"""
import time
# 创建中等规模数据
df = pd.DataFrame({
'A': np.random.randn(100000),
'B': np.random.randn(100000),
'C': np.random.randn(100000)
})
methods = {
'serial': lambda: df.apply(lambda x: sum([np.sin(v) for v in x]), axis=1),
'vectorized': lambda: np.sin(df['A']) + np.sin(df['B']) + np.sin(df['C']),
'swifter': lambda: df.swifter.apply(lambda x: sum([np.sin(v) for v in x]), axis=1),
'multiprocessing': lambda: parallel_processing(df)
}
for name, func in methods.items():
start = time.time()
result = func()
elapsed = time.time() - start
print(f"{name}: {elapsed:.3f}秒")
# 最佳实践总结
print("""
最佳实践建议:
1. 优先使用向量化操作(最快)
2. 数据量大时使用dask(可扩展到集群)
3. 普通并行使用swifter(最简单)
4. 复杂逻辑使用multiprocessing
5. IO密集型任务使用ThreadPoolExecutor
6. CPU密集型任务使用ProcessPoolExecutor
""")
注意事项
def parallel_cautions():
"""并行处理注意事项"""
warnings = """
1. 内存管理:
- 注意内存占用,避免内存溢出
- 使用array_split分割数据
2. 数据依赖:
- 确保数据分片之间没有依赖关系
- 保持数据类型一致性
3. 性能开销:
- 小数据集不适合并行(通信开销大)
- 数据量 < 10000行可能更慢
4. 调试困难:
- 并行代码难以调试
- 建议先在串行模式下验证
5. 资源管理:
- 不要使用所有核心(保留1-2个)
- 注意释放资源
"""
print(warnings)
parallel_cautions()
选择哪种方法取决于:
- 数据规模(小/中/大)
- 计算复杂度(简单/复杂)
- 环境限制(单机/集群)
- 开发效率要求
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播