@@ -1558,7 +1558,7 @@ cdef float64_t calc_weighted_var(float64_t t,
1558
1558
if nobs == 1 :
1559
1559
result = 0
1560
1560
else :
1561
- result = t * win_n / ((win_n - ddof) * sum_w)
1561
+ result = t * nobs / ((nobs - ddof) * sum_w)
1562
1562
if result < 0 :
1563
1563
result = 0
1564
1564
else :
@@ -1599,68 +1599,20 @@ cdef void add_weighted_var(float64_t val,
1599
1599
cdef:
1600
1600
float64_t temp, q, r
1601
1601
1602
- if val != val:
1603
- return
1604
-
1605
1602
nobs[0 ] = nobs[0 ] + 1
1606
1603
1607
- q = val - mean[0 ]
1608
- temp = sum_w[0 ] + w
1609
- r = q * w / temp
1610
-
1611
- mean[0 ] = mean[0 ] + r
1612
- t[0 ] = t[0 ] + r * sum_w[0 ] * q
1613
- sum_w[0 ] = temp
1614
-
1615
-
1616
- cdef void remove_weighted_var(float64_t val,
1617
- float64_t w,
1618
- float64_t * t,
1619
- float64_t * sum_w,
1620
- float64_t * mean,
1621
- float64_t * nobs) noexcept nogil:
1622
- """
1623
- Update weighted mean, sum of weights and sum of weighted squared
1624
- differences to remove value and weight pair from weighted variance
1625
- calculation using West's method.
1626
-
1627
- Paper: https://dl.acm.org/citation.cfm?id=359153
1628
-
1629
- Parameters
1630
- ----------
1631
- val: float64_t
1632
- window values
1633
- w: float64_t
1634
- window weights
1635
- t: float64_t
1636
- sum of weighted squared differences
1637
- sum_w: float64_t
1638
- sum of weights
1639
- mean: float64_t
1640
- weighted mean
1641
- nobs: float64_t
1642
- number of observations
1643
- """
1644
-
1645
- cdef:
1646
- float64_t temp, q, r
1647
-
1648
- if val == val:
1649
- nobs[0 ] = nobs[0 ] - 1
1650
-
1651
- if nobs[0 ]:
1652
- q = val - mean[0 ]
1653
- temp = sum_w[0 ] - w
1654
- r = q * w / temp
1604
+ if nobs[0 ] == 1 :
1605
+ sum_w[0 ] = w
1606
+ mean[0 ] = val
1655
1607
1656
- mean[0 ] = mean[0 ] - r
1657
- t[0 ] = t[0 ] - r * sum_w[0 ] * q
1658
- sum_w[0 ] = temp
1608
+ else :
1609
+ q = val - mean[0 ]
1610
+ temp = sum_w[0 ] + w
1611
+ r = q * w / temp
1659
1612
1660
- else :
1661
- t[0 ] = 0
1662
- sum_w[0 ] = 0
1663
- mean[0 ] = 0
1613
+ mean[0 ] = mean[0 ] + r
1614
+ t[0 ] = t[0 ] + r * sum_w[0 ] * q
1615
+ sum_w[0 ] = temp
1664
1616
1665
1617
1666
1618
def roll_weighted_var (const float64_t[:] values , const float64_t[:] weights ,
@@ -1690,44 +1642,38 @@ def roll_weighted_var(const float64_t[:] values, const float64_t[:] weights,
1690
1642
"""
1691
1643
1692
1644
cdef:
1693
- float64_t t = 0 , sum_w = 0 , mean = 0 , nobs = 0
1694
- float64_t val, pre_val, w, pre_w
1695
- Py_ssize_t i, n, win_n
1696
- float64_t[:] output
1645
+ float64_t val, w
1646
+ Py_ssize_t in_i, win_i, add_i, n, win_n
1647
+ float64_t[:] output, t, mean, sum_w, nobs
1697
1648
1698
1649
n = len (values)
1699
1650
win_n = len (weights)
1651
+
1700
1652
output = np.empty(n, dtype = np.float64)
1653
+ t = np.zeros(n, dtype = np.float64)
1654
+ mean = np.zeros(n, dtype = np.float64)
1655
+ sum_w = np.zeros(n, dtype = np.float64)
1656
+ nobs = np.zeros(n, dtype = np.float64)
1701
1657
1702
1658
with nogil:
1703
-
1704
- for i in range (min (win_n, n)):
1705
- add_weighted_var(values[i], weights[i], & t,
1706
- & sum_w, & mean, & nobs)
1707
-
1708
- output[i] = calc_weighted_var(t, sum_w, win_n,
1709
- ddof, nobs, minp)
1710
-
1711
- for i in range (win_n, n):
1712
- val = values[i]
1713
- pre_val = values[i - win_n]
1714
-
1715
- w = weights[i % win_n]
1716
- pre_w = weights[(i - win_n) % win_n]
1717
-
1718
- if val == val:
1719
- if pre_val == pre_val:
1720
- remove_weighted_var(pre_val, pre_w, & t,
1721
- & sum_w, & mean, & nobs)
1722
-
1723
- add_weighted_var(val, w, & t, & sum_w, & mean, & nobs)
1724
-
1725
- elif pre_val == pre_val:
1726
- remove_weighted_var(pre_val, pre_w, & t,
1727
- & sum_w, & mean, & nobs)
1728
-
1729
- output[i] = calc_weighted_var(t, sum_w, win_n,
1730
- ddof, nobs, minp)
1659
+ for win_i in range (win_n):
1660
+ w = weights[win_i]
1661
+ if w != w:
1662
+ continue
1663
+
1664
+ for in_i in range (n - (win_n - win_i) + 1 ):
1665
+ val = values[in_i]
1666
+
1667
+ if val == val:
1668
+ add_i = in_i + (win_n - win_i) - 1
1669
+ add_weighted_var(
1670
+ val, w, & t[add_i], & sum_w[add_i], & mean[add_i], & nobs[add_i]
1671
+ )
1672
+
1673
+ for in_i in range (n):
1674
+ output[in_i] = calc_weighted_var(
1675
+ t[in_i], sum_w[in_i], win_n, ddof, nobs[in_i], minp
1676
+ )
1731
1677
1732
1678
return output
1733
1679
0 commit comments