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

Python如何计算非数值字符串类型风向数据的平均值

风向平均值计算解决方案

核心原理

风向属于环形角度值,直接做算术平均会出现逻辑错误(比如0°北风和359°北风的算术平均是179.5°南风,和实际情况完全不符)。正确的计算逻辑是先把风向分解为东西(u)、南北(v)两个矢量分量,对分量求平均后再转换回角度,最后映射为风向字符串,全程可借助numpy的向量运算能力实现,无需循环遍历,处理效率极高。

实现步骤

  • 步骤1:建立16方位风向和角度的映射关系(如果你的数据是8方位,调整映射字典即可)
  • 步骤2:将数据中的风向字符串转换为对应角度
  • 步骤3:利用numpy向量运算将角度分解为u、v分量,计算分量均值
  • 步骤4:将平均分量转换为0~360°范围内的平均角度,再映射回风向字符串

完整代码示例

import pandas as pd
import numpy as np

# 16方位风向对应的角度(以北为0°,顺时针递增)
DIR_TO_DEG = {
    'N': 0, 'NNE': 22.5, 'NE': 45, 'ENE': 67.5,
    'E': 90, 'ESE': 112.5, 'SE': 135, 'SSE': 157.5,
    'S': 180, 'SSW': 202.5, 'SW': 225, 'WSW': 247.5,
    'W': 270, 'WNW': 292.5, 'NW': 315, 'NNW': 337.5
}
# 反向映射:角度转风向
DEG_TO_DIR = {v: k for k, v in DIR_TO_DEG.items()}

def calc_mean_wind_dir(wind_dir_series):
    # 风向字符串转角度
    deg_series = wind_dir_series.map(DIR_TO_DEG)
    # 角度转弧度,分解为u、v分量(全向量运算,无循环)
    rad = np.radians(deg_series)
    u = np.sin(rad)
    v = np.cos(rad)
    # 计算分量均值
    u_mean = u.mean()
    v_mean = v.mean()
    # 处理无风场景:各方向风矢量完全抵消,风向无意义
    if np.isclose(u_mean, 0) and np.isclose(v_mean, 0):
        return np.nan, np.nan
    # 平均分量转角度,调整到0~360范围
    mean_rad = np.arctan2(u_mean, v_mean)
    mean_deg = np.degrees(mean_rad) % 360
    # 匹配最近的风向字符串
    closest_deg = min(DEG_TO_DIR.keys(), key=lambda x: abs(x - mean_deg))
    return DEG_TO_DIR[closest_deg], mean_deg

# 测试用例,对应你给出的示例数据
df = pd.DataFrame({
    'time': ['2010-08-27 00:00:00', '2010-08-27 00:15:00', '2010-08-27 00:30:00', '2010-08-27 00:45:00', '2010-08-27 01:00:00'],
    'wind_dir': ['SW', 'SSW', 'SSW', 'SSE', 'NNE']
})

# 调用函数计算平均风向
mean_dir_str, mean_dir_deg = calc_mean_wind_dir(df['wind_dir'])
print(f"平均风向角度:{mean_dir_deg:.2f},对应风向:{mean_dir_str}")

扩展说明

如果需要按时间窗口(比如每小时、每天)计算平均风向,搭配pandas的resample方法即可,整个运算过程都是向量化执行,百万行级别的时序数据也可以在秒级完成计算。

内容的提问来源于stack exchange,提问作者Martín

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 18:54:05