You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何加速DataFrame循环处理?宽表转换优化方案

优化DataFrame宽表转换的嵌套循环速度问题

问题描述

我需要遍历DataFrame中的每个纬度和经度,将数据转换为指定的宽表格式,但当前嵌套for循环的处理速度极慢。请问能否通过多线程、多进程等方式优化该脚本?请给出具体实现方法。

原始代码

p=0
for i in tqdm(df_wind_monthly["lat"]):
    for j in df_wind_monthly["lon"]:
        print("lat: " + str(i) + " lon: " + str(j))
        for k in range(1948,2017): 
            rslt_df_wind = df_wind_monthly.loc[(df_wind_monthly['lat'] == i) \
                                          & (df_wind_monthly['lon'] == j) \
                                              & (df_wind_monthly['year'] == k)]; rslt_df_wind = rslt_df_wind.reset_index()
            month_columns.loc[p,"lat"]=rslt_df_wind.loc[0,"lat"]
            month_columns.loc[p,"lon"]=rslt_df_wind.loc[0,"lon"]
            month_columns.loc[p,"years"]=rslt_df_wind.loc[0,"year"]
            month_columns.loc[p,"wind_January"]=rslt_df_wind.loc[rslt_df_wind['month'].loc[lambda x: x=="January"].index.tolist()[0],"wind"]
            month_columns.loc[p,"wind_February"]=rslt_df_wind.loc[rslt_df_wind['month'].loc[lambda x: x=="February"].index.tolist()[0],"wind"]
            month_columns.loc[p,"wind_March"]=rslt_df_wind.loc[rslt_df_wind['month'].loc[lambda x: x=="March"].index.tolist()[0],"wind"]
            month_columns.loc[p,"wind_April"]=rslt_df_wind.loc[rslt_df_wind['month'].loc[lambda x: x=="April"].index.tolist()[0],"wind"]
            month_columns.loc[p,"wind_May"]=rslt_df_wind.loc[rslt_df_wind['month'].loc[lambda x: x=="May"].index.tolist()[0],"wind"]
            month_columns.loc[p,"wind_June"]=rslt_df_wind.loc[rslt_df_wind['month'].loc[lambda x: x=="June"].index.tolist()[0],"wind"]
            month_columns.loc[p,"wind_July"]=rslt_df_wind.loc[rslt_df_wind['month'].loc[lambda x: x=="July"].index.tolist()[0],"wind"]
            month_columns.loc[p,"wind_August"]=rslt_df_wind.loc[rslt_df_wind['month'].loc[lambda x: x=="August"].index.tolist()[0],"wind"]
            month_columns.loc[p,"wind_September"]=rslt_df_wind.loc[rslt_df_wind['month'].loc[lambda x: x=="September"].index.tolist()[0],"wind"]
            month_columns.loc[p,"wind_October"]=rslt_df_wind.loc[rslt_df_wind['month'].loc[lambda x: x=="October"].index.tolist()[0],"wind"]
            month_columns.loc[p,"wind_November"]=rslt_df_wind.loc[rslt_df_wind['month'].loc[lambda x: x=="November"].index.tolist()[0],"wind"]
            month_columns.loc[p,"wind_December"]=rslt_df_wind.loc[rslt_df_wind['month'].loc[lambda x: x=="December"].index.tolist()[0],"wind"]
            p+=1

输入输出示例

输入DataFrame(df_wind_monthly):

time     lat     lon      wind
0       1948-01-16  15.125  15.125  6.509021
1       1948-01-16  15.125  15.375  6.485108
2       1948-01-16  15.125  15.625  6.472615
3       1948-01-16  15.125  15.875  6.472596
4       1948-01-16  15.125  16.125  6.486597

目标输出DataFrame结构:

month_columns=pd.DataFrame(columns=['lat',"lon","years","wind_January","wind_February","wind_March","wind_April","wind_May","wind_June","wind_July","wind_August","wind_September","wind_October","wind_November","wind_December"])

优化方案

方案1:优先使用Pandas原生透视表(最快最简洁)

你的核心需求是将长表转换为宽表,这完全可以通过Pandas的pivot_table实现,无需嵌套循环。这种矢量化操作比循环快几个数量级,是最优解。

import pandas as pd

# 1. 从time列提取年份和月份名称
df_wind_monthly['year'] = pd.to_datetime(df_wind_monthly['time']).dt.year
df_wind_monthly['month'] = pd.to_datetime(df_wind_monthly['time']).dt.month_name()

# 2. 定义月份列名映射
month_mapping = {
    'January': 'wind_January',
    'February': 'wind_February',
    'March': 'wind_March',
    'April': 'wind_April',
    'May': 'wind_May',
    'June': 'wind_June',
    'July': 'wind_July',
    'August': 'wind_August',
    'September': 'wind_September',
    'October': 'wind_October',
    'November': 'wind_November',
    'December': 'wind_December'
}

# 3. 生成透视表
result = df_wind_monthly.pivot_table(
    index=['lat', 'lon', 'year'],
    columns='month',
    values='wind',
    aggfunc='first'  # 假设每个(lat, lon, year, month)组合唯一
).reset_index()

# 4. 调整列名和顺序
result = result.rename(columns=month_mapping)
result = result.rename(columns={'year': 'years'})

# 匹配目标列顺序
target_columns = ['lat', 'lon', 'years', 'wind_January', 'wind_February', 'wind_March', 
                  'wind_April', 'wind_May', 'wind_June', 'wind_July', 'wind_August', 
                  'wind_September', 'wind_October', 'wind_November', 'wind_December']
result = result[target_columns]

方案2:多进程优化(仅适用于超大规模数据)

如果数据量极大,透视表仍有性能瓶颈,可以用多进程并行处理分组数据。由于Python的GIL限制,多线程对计算密集型任务提升有限,优先用多进程。

import pandas as pd
from multiprocessing import Pool, cpu_count

# 预处理:提取年份和月份
df_wind_monthly['year'] = pd.to_datetime(df_wind_monthly['time']).dt.year
df_wind_monthly['month'] = pd.to_datetime(df_wind_monthly['time']).dt.month_name()

# 定义月份映射和目标列(同方案1)
month_mapping = {
    'January': 'wind_January',
    'February': 'wind_February',
    'March': 'wind_March',
    'April': 'wind_April',
    'May': 'wind_May',
    'June': 'wind_June',
    'July': 'wind_July',
    'August': 'wind_August',
    'September': 'wind_September',
    'October': 'wind_October',
    'November': 'wind_November',
    'December': 'wind_December'
}
target_columns = ['lat', 'lon', 'years', 'wind_January', 'wind_February', 'wind_March', 
                  'wind_April', 'wind_May', 'wind_June', 'wind_July', 'wind_August', 
                  'wind_September', 'wind_October', 'wind_November', 'wind_December']

# 定义单分组处理函数
def process_group(group):
    lat, lon = group.name
    # 分组内生成透视表
    group_pivot = group.pivot_table(
        index='year',
        columns='month',
        values='wind',
        aggfunc='first'
    ).reset_index()
    # 添加经纬度列
    group_pivot['lat'] = lat
    group_pivot['lon'] = lon
    # 调整列名和顺序
    group_pivot = group_pivot.rename(columns=month_mapping)
    group_pivot = group_pivot.rename(columns={'year': 'years'})
    return group_pivot[target_columns]

# 多进程执行
if __name__ == '__main__':
    # 按经纬度分组
    groups = df_wind_monthly.groupby(['lat', 'lon'])
    # 使用CPU核心数-1避免资源耗尽
    with Pool(cpu_count() - 1) as pool:
        processed_results = pool.map(process_group, groups)
    # 合并所有结果
    final_result = pd.concat(processed_results, ignore_index=True)

内容的提问来源于stack exchange,提问作者fyec

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 15:10:43