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

使用PVLIB转换辐照度时生成NaN值问题排查

解决PVLIB转换水平面辐照度到垂直面时生成NaN的问题

看起来你在把PVGIS的小时级水平面数据转成西向垂直面辐照度时遇到了NaN的问题,我帮你梳理几个最可能的原因和解决办法:

1. 未定义location对象导致太阳位置计算错误

你代码里用了location.latitude和location.longitude,但前面只定义了单独的latitude = 45.466和longitude = 9.183,没有创建对应的location对象!这会直接导致太阳位置计算失败,得到的solpos数据大概率全是NaN,后续辐照度转换自然也会输出NaN。

修正方法:
要么直接用你已经定义好的经纬度参数,要么规范创建pvlib的Location对象:

# 方法1:直接使用已定义的经纬度
solpos = pvlib.solarposition.get_solarposition(
    times,
    latitude,
    longitude
)

# 方法2:创建Location对象(更符合pvlib使用规范)
location = pvlib.location.Location(latitude, longitude, timezone=timezone, altitude=altitude)
solpos = location.get_solarposition(times)

2. 时间序列未对齐(高频触发原因)

你手动生成了times时间序列,但没有确保它和CSV读取的irrad_horz_ERA5['Date']完全匹配:

  • 检查CSV读取的Date列是否设置了时区(你给times指定了Europe/Rome,但原始CSV的日期是 naive 状态)
  • 确认两个时间序列的长度、时间戳完全对应(比如你生成了52584个小时,要确保CSV的行数也是52584行)

优化方案:
直接用CSV中的Date列作为太阳位置计算的时间输入,避免手动生成的偏差:

# 给读取的日期列设置时区
irrad_horz_ERA5['Date'] = irrad_horz_ERA5['Date'].dt.tz_localize('Europe/Rome')
# 用该时间列计算太阳位置
solpos = pvlib.solarposition.get_solarposition(
    irrad_horz_ERA5['Date'],
    latitude,
    longitude
)

3. 原始CSV数据存在缺失值

检查你的ghi、Bi、Di列本身是否就有NaN值:

print(irrad_horz_ERA5[['ghi', 'Bi', 'Di']].isna().sum())

如果原始数据存在缺失,转换后的结果自然会出现NaN。可以用线性插值填充:

irrad_horz_ERA5[['ghi', 'Bi', 'Di']] = irrad_horz_ERA5[['ghi', 'Bi', 'Di']].interpolate(method='linear')

4. 太阳在地平线以下的正常情况

当太阳天顶角(apparent_zenith)大于90度时,说明太阳未升起或已落下,此时get_total_irradiance会返回NaN,这是合理现象。你可以把这些NaN替换为0:

westERA5 = westERA5.fillna(0)

修正后的完整代码片段

import pandas as pd
import pvlib

# 创建lambda函数解析csv中的日期
mydateparser = lambda x: pd.datetime.strptime(x, "%Y%m%d:%H%M")
irrad_horz_ERA5 = pd.read_csv(
    (r'C:\Users\dpaul\OneDrive\1st part\Downloaded csv\PVGISERA5\Horizontal'
     r'\Timeseries_45.467_9.191_E5__0deg_0deg_2010_2016.csv'),
    parse_dates=['Date'],
    date_parser=mydateparser)

# 为日期列设置时区
irrad_horz_ERA5['Date'] = irrad_horz_ERA5['Date'].dt.tz_localize('Europe/Rome')

latitude = 45.466
longitude = 9.183
altitude = 120
timezone = 'Europe/Rome'
ground_albedo = 0.2

# 基于CSV的时间列计算太阳位置
solpos = pvlib.solarposition.get_solarposition(
    irrad_horz_ERA5['Date'],
    latitude,
    longitude
)

# 确保数值类型正确
columns = ['apparent_zenith', 'azimuth']
solpos[columns] = solpos[columns].apply(pd.to_numeric, axis=1)
cols = ['ghi', 'Bi', 'Di']
irrad_horz_ERA5[cols] = irrad_horz_ERA5[cols].apply(pd.to_numeric, axis=1)

# 填充原始数据缺失值
irrad_horz_ERA5[cols] = irrad_horz_ERA5[cols].interpolate(method='linear')

# 计算西向垂直面辐照度
westERA5 = pvlib.irradiance.get_total_irradiance(
    surface_tilt=90,
    surface_azimuth=270,
    solar_zenith=solpos.apparent_zenith,
    solar_azimuth=solpos.azimuth,
    ghi=irrad_horz_ERA5.ghi,
    dni=irrad_horz_ERA5.Bi,
    dhi=irrad_horz_ERA5.Di,
    albedo=ground_albedo
)

# 替换太阳未升起时的NaN为0
westERA5 = westERA5.fillna(0)

print(westERA5.head(20))

建议先排查location对象的问题,这是最可能导致全量NaN的原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:42:29