Skip to content

Commit 969d39b

Browse files
committed
Fix delta_kt_prime halving single valid neighbor difference (gh-1847)
In irradiance._delta_kt_prime_dirint, when an interior point has only one valid neighbor (a missing value elsewhere in the series), the previous code substituted 0 for the missing neighbor difference and then multiplied by 0.5, halving the remaining valid difference. This produced an incorrect stability index delta_kt_prime and, downstream, incorrect DIRINT beam irradiance. Replace the manual endpoint patching with a row-wise mean of the next and previous absolute differences. pandas skips NaN values, so Perez eqn 2 (two neighbors), eqn 3 for endpoints, and interior gaps with one missing neighbor are all handled correctly. Add a regression test and a whatsnew entry.
1 parent 9a0ad55 commit 969d39b

3 files changed

Lines changed: 27 additions & 9 deletions

File tree

docs/sphinx/source/whatsnew/v0.15.3.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ Deprecations
1313

1414

1515
Bug fixes
16-
~~~~~~~~~
16+
~~~~~~~~
17+
18+
* Fixed ``irradiance.dirint`` so that an interior missing value in the input
19+
series no longer halves the single valid neighbor difference when computing
20+
the stability index ``delta_kt_prime`` (Perez eqn 3). (:issue:`1847`)
1721

1822

1923
Enhancements
@@ -53,4 +57,5 @@ Contributors
5357
* Karl Hill (:ghuser:`karlhillx`)
5458
* Mathias Aschwanden (:ghuser:`maschwanden`)
5559
* Yonry Zhu (:ghuser:`yonryzhu`)
60+
* Aditya (:ghuser:`adi-IL`)
5661
* Darshan Gowda (:ghuser:`dgowdaan-cmyk`)

pvlib/irradiance.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2035,16 +2035,18 @@ def _delta_kt_prime_dirint(kt_prime, use_delta_kt_prime, times):
20352035
for use with :py:func:`_dirint_bins`.
20362036
"""
20372037
if use_delta_kt_prime:
2038-
# Perez eqn 2
2038+
# Perez eqn 2 (interior points). Perez eqn 3 (boundary points and
2039+
# interior gaps where one neighbor is missing) is handled by taking
2040+
# the row-wise mean, which averages zero, one, or two valid neighbor
2041+
# differences because pandas skips NaN values. This avoids the
2042+
# previous behavior of halving a single valid difference when one
2043+
# neighbor is NaN (gh-1847).
20392044
kt_next = kt_prime.shift(-1)
20402045
kt_previous = kt_prime.shift(1)
2041-
# replace nan with values that implement Perez Eq 3 for first and last
2042-
# positions. Use kt_previous and kt_next to handle series of length 1
2043-
kt_next.iloc[-1] = kt_previous.iloc[-1]
2044-
kt_previous.iloc[0] = kt_next.iloc[0]
2045-
delta_kt_prime = 0.5 * ((kt_prime - kt_next).abs().add(
2046-
(kt_prime - kt_previous).abs(),
2047-
fill_value=0))
2046+
delta_kt_prime = pd.DataFrame({
2047+
'next': (kt_prime - kt_next).abs(),
2048+
'prev': (kt_prime - kt_previous).abs(),
2049+
}).mean(axis=1)
20482050
else:
20492051
# do not change unless also modifying _dirint_bins
20502052
delta_kt_prime = pd.Series(-1, index=times)

tests/test_irradiance.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,17 @@ def test_dirint_nans():
719719
np.array([np.nan, np.nan, np.nan, np.nan, 893.1]), 1)
720720

721721

722+
def test_delta_kt_prime_interior_nan():
723+
# regression test for gh-1847: an interior NaN in kt_prime must not
724+
# halve the single valid neighbor difference. When only one neighbor
725+
# is available (Perez eqn 3) delta_kt_prime equals that difference.
726+
times = pd.date_range(start='2020-01-01', periods=5, freq='1h')
727+
kt_prime = pd.Series([0.5, 0.6, np.nan, 0.7, 0.4], index=times)
728+
result = irradiance._delta_kt_prime_dirint(kt_prime, True, times)
729+
expected = pd.Series([0.1, 0.1, np.nan, 0.3, 0.3], index=times)
730+
assert_series_equal(result, expected)
731+
732+
722733
def test_dirint_tdew():
723734
times = pd.DatetimeIndex(['2014-06-24T12-0700', '2014-06-24T18-0700'])
724735
ghi = pd.Series([1038.62, 254.53], index=times)

0 commit comments

Comments
 (0)