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

如何使用Cython优化数组循环以提升处理效率?

用Cython优化栅格作物面积分配的数组迭代

先分析原代码的性能瓶颈

你的代码慢主要有两个核心问题:

  1. 三重嵌套循环+冗余赋值:内层循环每次给所有栅格单元的Maize列赋同一个值,最终只会保留最后一次循环的结果,逻辑上存在大量冗余计算。
  2. Pandas loc的高开销:循环内频繁调用df_area.loc[n,"Maize"],这是带标签查找的高层操作,每次调用都有Python对象的额外开销,循环次数多了会严重拖慢速度。

优先尝试NumPy向量化优化(比Cython更易实现)

如果你的数据结构是每个栅格对应12个月的记录,可直接用NumPy的向量化操作替代循环,性能提升会非常明显:

import numpy as np
import pandas as pd

# 提取玉米生长季的起止月份
k = df_dist.Planting_month[5]
l = df_dist.Maturity_month[5]
start_month = min(k, l)
end_month = max(k, l)

# 假设arr_5是对应每个栅格的玉米面积数组(形状为(N,),N是栅格数量)
# 生成生长季月份的掩码(匹配df_area中属于生长季的行)
month_mask = df_area['month'].isin(range(start_month, end_month + 1))

# 为生长季的行赋值:每个栅格对应end_month - start_month + 1个月份,重复arr_5的值
df_area.loc[month_mask, 'Maize'] = np.repeat(arr_5, end_month - start_month + 1)

用Cython进一步优化(适合超大规模数据)

如果NumPy的速度还不够,可通过Cython将循环编译为纯C代码,彻底消除Python解释器的开销:

步骤1:编写Cython代码文件(crop_area.pyx)

import numpy as np
cimport numpy as np
cimport cython

# 关闭边界检查和负索引检查,提升运行速度
@cython.boundscheck(False)
@cython.wraparound(False)
def assign_maize_area(
    np.ndarray[np.float64_t, ndim=1] grid_area,  # 每个栅格的玉米面积
    np.ndarray[np.int32_t, ndim=1] row_months,  # df_area每行对应的月份
    int start_month, 
    int end_month,
    np.ndarray[np.float64_t, ndim=1] maize_column  # df_area['Maize']的NumPy视图
):
    cdef int total_rows = row_months.shape[0]
    cdef int grid_count = grid_area.shape[0]
    cdef int row_idx, grid_idx
    
    # 遍历所有行,根据月份判断是否属于生长季,直接赋值
    for row_idx in range(total_rows):
        # 每个栅格对应连续12个月,计算当前行所属的栅格索引
        grid_idx = row_idx // 12
        if start_month <= row_months[row_idx] <= end_month:
            maize_column[row_idx] = grid_area[grid_idx]

步骤2:编写编译脚本(setup.py)

from setuptools import setup
from Cython.Build import cythonize
import numpy as np

setup(
    ext_modules=cythonize("crop_area.pyx"),
    include_dirs=[np.get_include()]
)

步骤3:编译并调用

运行以下命令编译Cython代码:

python setup.py build_ext --inplace

在主代码中调用编译后的函数:

import numpy as np
import pandas as pd
from crop_area import assign_maize_area

# 准备输入数据
grid_area = maz_st_1  # 每个栅格的玉米面积数组(形状为(N,))
row_months = df_area['month'].values  # df_area每行的月份(NumPy数组)
start_month = min(df_dist.Planting_month[5], df_dist.Maturity_month[5])
end_month = max(df_dist.Planting_month[5], df_dist.Maturity_month[5])
maize_col = df_area['Maize'].values  # 直接操作NumPy数组视图,避免Pandas开销

# 执行Cython优化的赋值操作
assign_maize_area(grid_area, row_months, start_month, end_month, maize_col)

# 可选:将结果写回DataFrame
df_area['Maize'] = maize_col

Cython优化的核心点

  • 静态类型声明:用cdef声明变量和数组类型,让Cython生成纯C代码,避免Python对象的运行时开销。
  • 关闭安全检查:boundscheck(False)和wraparound(False)关闭不必要的边界和负索引检查,进一步提升速度。
  • 直接操作内存:通过NumPy数组的底层内存进行赋值,完全绕过Pandas的高层API开销。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 11:20:26