Rolling#

class pandas::Rolling#

Window operation class for rolling/expanding calculations.

Example#

#include <pandas/pandas.h>
using namespace pandas;

// Use Rolling
Rolling obj;
// ... operations ...

Constructors#

Signature

Location

Example

Rolling(const Series<T>& series, size_t window, size_t min_periods = 1, bool center = false)

pd_rolling.h:62

Indexing / Selection#

Signature

Return Type

Location

Example

const Series<T>& get_series() const

const Series<T>&

pd_rolling.h:93

View

size_t get_window() const

size_t

pd_rolling.h:94

std::pair<size_t, size_t> get_window_bounds(size_t i) const

std::pair<size_t, size_t>

pd_rolling.h:424

std::vector<double> get_window_values(size_t start, size_t end) const

std::vector<double>

pd_rolling.h:500

Statistics#

Signature

Return Type

Location

Example

Series<double> count() const

Series<double>

pd_rolling.h:124

View

Series<double> kurt() const

Series<double>

pd_rolling.h:204

View

Series<double> max() const

Series<double>

pd_rolling.h:118

View

Series<double> mean() const

Series<double>

pd_rolling.h:106

View

Series<double> median() const

Series<double>

pd_rolling.h:158

View

Series<double> min() const

Series<double>

pd_rolling.h:112

View

Series<double> quantile(double q) const

Series<double>

pd_rolling.h:231

View

Series<double> sem(int ddof = 1) const

Series<double>

pd_rolling.h:252

View

Series<double> skew() const

Series<double>

pd_rolling.h:178

View

Series<double> std_(int ddof = 1) const

Series<double>

pd_rolling.h:130

View

Series<double> sum() const

Series<double>

pd_rolling.h:100

View

Series<double> var(int ddof = 1) const

Series<double>

pd_rolling.h:144

View

Aggregation#

Signature

Return Type

Location

Example

Series<double> apply(Func&& func) const

Series<double>

pd_rolling.h:415

View

Series<double> apply_rolling(Func&& func) const

Series<double>

pd_rolling.h:524

Sorting#

Signature

Return Type

Location

Example

Series<double> rank() const

Series<double>

pd_rolling.h:274

View

Type Checking#

Signature

Return Type

Location

Example

bool is_custom_bounds() const

bool

pd_rolling.h:91

bool is_time_based() const

bool

pd_rolling.h:83

View

Other Methods#

Signature

Return Type

Location

Example

Series<double> corr(const Series<T>& other) const

Series<double>

pd_rolling.h:357

View

Series<double> cov(const Series<T>& other, int ddof = 1) const

Series<double>

pd_rolling.h:291

View

propagate_source_index(result_series)

pd_rolling.h:267

propagate_source_index(result_series)

pd_rolling.h:349

propagate_source_index(result_series)

pd_rolling.h:406

propagate_source_index(result_series)

pd_rolling.h:540

void propagate_source_index(Series<double>& result) const

void

pd_rolling.h:547

void set_custom_bounds(std::vector<int64_t> start, std::vector<int64_t> end)

void

pd_rolling.h:85

void set_time_window(std::vector<int64_t> timestamps, int64_t window_seconds, int closed = 0)

void

pd_rolling.h:75

Code Examples#

The following examples are extracted from the test suite.

get_series (pd_test_5_all.cpp:12970)
12960        pandas_tests::check(!threw, "query_bool_and_numeric.no_throw", local_fail);
12961        if (!threw) {
12962            pandas_tests::check(result.nrows() == 1, "query_bool_and_numeric.nrows == 1 (got " + std::to_string(result.nrows()) + ")", local_fail);
12963        }
12964    }
12965
12966    // === xs_level tests (Error 2) ===
12967    // Note: xs_level() doesn't exist yet — test will verify it after implementation
12968
12969    // === get_series + unstack tests (Error 1) ===
12970    // Note: get_series<T>() doesn't exist yet — test will verify it after implementation
12971
12972    if (local_fail > 0) {
12973        std::cout << "  [FAIL] : in f_test_anal_i_query_bool_unstack() : " << local_fail << " checks failed" << std::endl;
12974        throw std::runtime_error("f_test_anal_i_query_bool_unstack failed");
12975    }
12976    std::cout << " -> tests passed" << std::endl;
12977}
12978
12979
12980// --- cpp_f_test_zanal_a_column_width.cpp ---
count (pd_test_1_all.cpp:66)
56        if (arr.is_na(0)) {
57            std::cout << "  [FAIL] : in pd_test_boolean_array_na_handling() : is_na(0) should be false" << std::endl;
58            throw std::runtime_error("pd_test_boolean_array_na_handling failed: is_na(0) should be false");
59        }
60
61        if (!arr.has_na()) {
62            std::cout << "  [FAIL] : in pd_test_boolean_array_na_handling() : has_na() should be true" << std::endl;
63            throw std::runtime_error("pd_test_boolean_array_na_handling failed: has_na() should be true");
64        }
65
66        if (arr.count() != 2) {
67            std::cout << "  [FAIL] : in pd_test_boolean_array_na_handling() : count() should be 2" << std::endl;
68            throw std::runtime_error("pd_test_boolean_array_na_handling failed: count() should be 2");
69        }
70
71        std::cout << " -> tests passed" << std::endl;
72    }
73
74    void pd_test_boolean_array_kleene_and() {
75        std::cout << "========= BooleanArray: Kleene AND ======================= ";
kurt (pd_test_1_all.cpp:4599)
4589            std::cout << "========= Series skew/kurt ======================";
4590
4591            pandas::Series<double> s({1.0, 2.0, 2.0, 3.0, 9.0});
4592            auto skew_val = s.skew();
4593            bool passed = skew_val.has_value() && *skew_val > 0;  // Should be right-skewed
4594            if (!passed) {
4595                std::cout << "  [FAIL] : in pd_test_aggregation_series_skew_kurt() : skew should be positive" << std::endl;
4596                throw std::runtime_error("pd_test_aggregation_series_skew_kurt failed: skew should be positive");
4597            }
4598
4599            auto kurt_val = s.kurt();
4600            passed = kurt_val.has_value();
4601            if (!passed) {
4602                std::cout << "  [FAIL] : in pd_test_aggregation_series_skew_kurt() : kurt should have value" << std::endl;
4603                throw std::runtime_error("pd_test_aggregation_series_skew_kurt failed: kurt should have value");
4604            }
4605
4606            // Test kurtosis alias
4607            auto kurt_alias = s.kurtosis();
4608            passed = kurt_alias.has_value() && std::abs(*kurt_alias - *kurt_val) < 0.0001;
4609            if (!passed) {
max (pd_test_1_all.cpp:771)
761        pandas::CategoricalArray arr = pandas::CategoricalArray::from_codes(codes, cats, true);  // ordered
762
763        // Test min
764        std::optional<std::string> min_val = arr.min();
765        if (!min_val.has_value() || *min_val != "low") {
766            std::cout << "  [FAIL] : in pd_test_categorical_array_ordered_operations() : min != 'low'" << std::endl;
767            throw std::runtime_error("pd_test_categorical_array_ordered_operations failed: min != 'low'");
768        }
769
770        // Test max
771        std::optional<std::string> max_val = arr.max();
772        if (!max_val.has_value() || *max_val != "high") {
773            std::cout << "  [FAIL] : in pd_test_categorical_array_ordered_operations() : max != 'high'" << std::endl;
774            throw std::runtime_error("pd_test_categorical_array_ordered_operations failed: max != 'high'");
775        }
776
777        // Test unordered throws for min/max
778        pandas::CategoricalArray unordered = arr.as_unordered();
779        bool threw = false;
780        try {
781            unordered.min();
mean (pd_test_1_all.cpp:282)
272            std::optional<bool>(true),
273            std::optional<bool>(true)
274        });
275
276        auto s = arr.sum();
277        if (!s.has_value() || s.value() != 3) {
278            std::cout << "  [FAIL] : in pd_test_boolean_array_reductions() : sum should be 3" << std::endl;
279            throw std::runtime_error("pd_test_boolean_array_reductions failed: sum");
280        }
281
282        auto m = arr.mean();
283        if (!m.has_value() || std::abs(m.value() - 0.75) > 0.001) {
284            std::cout << "  [FAIL] : in pd_test_boolean_array_reductions() : mean should be 0.75" << std::endl;
285            throw std::runtime_error("pd_test_boolean_array_reductions failed: mean");
286        }
287
288        std::cout << " -> tests passed" << std::endl;
289    }
290
291    void pd_test_boolean_array_dtype() {
292        std::cout << "========= BooleanArray: dtype ======================= ";
median (pd_test_1_all.cpp:20910)
20900                throw std::runtime_error("pd_test_expanding_var failed: expanding var values incorrect");
20901            }
20902
20903            std::cout << " -> tests passed" << std::endl;
20904        }
20905
20906        void pd_test_expanding_median() {
20907            std::cout << "========= Expanding median ======================";
20908
20909            pandas::Series<double> s({1.0, 2.0, 3.0, 4.0, 5.0});
20910            auto result = s.expanding().median();
20911
20912            // Expanding median: 1, 1.5, 2, 2.5, 3
20913            bool passed = std::abs(result[0] - 1.0) < 0.001 &&
20914                          std::abs(result[1] - 1.5) < 0.001 &&
20915                          std::abs(result[2] - 2.0) < 0.001 &&
20916                          std::abs(result[3] - 2.5) < 0.001 &&
20917                          std::abs(result[4] - 3.0) < 0.001;
20918            if (!passed) {
20919                std::cout << "  [FAIL] : in pd_test_expanding_median() : expanding median values incorrect" << std::endl;
20920                throw std::runtime_error("pd_test_expanding_median failed: expanding median values incorrect");
min (pd_test_1_all.cpp:764)
754    }
755
756    void pd_test_categorical_array_ordered_operations() {
757        std::cout << "========= CategoricalArray: ordered operations (min/max) ======================= ";
758
759        std::vector<std::string> cats = {"low", "medium", "high"};
760        std::vector<numpy::int32> codes = {0, 2, 1, 0, -1};  // low, high, medium, low, NA
761        pandas::CategoricalArray arr = pandas::CategoricalArray::from_codes(codes, cats, true);  // ordered
762
763        // Test min
764        std::optional<std::string> min_val = arr.min();
765        if (!min_val.has_value() || *min_val != "low") {
766            std::cout << "  [FAIL] : in pd_test_categorical_array_ordered_operations() : min != 'low'" << std::endl;
767            throw std::runtime_error("pd_test_categorical_array_ordered_operations failed: min != 'low'");
768        }
769
770        // Test max
771        std::optional<std::string> max_val = arr.max();
772        if (!max_val.has_value() || *max_val != "high") {
773            std::cout << "  [FAIL] : in pd_test_categorical_array_ordered_operations() : max != 'high'" << std::endl;
774            throw std::runtime_error("pd_test_categorical_array_ordered_operations failed: max != 'high'");
quantile (pd_test_1_all.cpp:4540)
4530                throw std::runtime_error("pd_test_aggregation_series_sem failed: sem value incorrect");
4531            }
4532
4533            std::cout << " -> tests passed" << std::endl;
4534        }
4535
4536        void pd_test_aggregation_series_quantile() {
4537            std::cout << "========= Series quantile =======================";
4538
4539            pandas::Series<double> s({1.0, 2.0, 3.0, 4.0, 5.0});
4540            auto q50 = s.quantile(0.5);
4541            bool passed = q50.has_value() && std::abs(*q50 - 3.0) < 0.001;
4542            if (!passed) {
4543                std::cout << "  [FAIL] : in pd_test_aggregation_series_quantile() : quantile(0.5) should be 3.0" << std::endl;
4544                throw std::runtime_error("pd_test_aggregation_series_quantile failed: quantile(0.5) should be 3.0");
4545            }
4546
4547            // Test q=0 and q=1
4548            auto q0 = s.quantile(0.0);
4549            passed = q0.has_value() && std::abs(*q0 - 1.0) < 0.001;
4550            if (!passed) {
sem (pd_test_1_all.cpp:4525)
4515#include "../pandas/pd_dataframe.h"
4516#include "../pandas/pd_series.h"
4517
4518namespace dataframe_tests {
4519    namespace dataframe_tests_aggregation {
4520
4521        void pd_test_aggregation_series_sem() {
4522            std::cout << "========= Series sem ============================";
4523
4524            pandas::Series<double> s({1.0, 2.0, 3.0, 4.0, 5.0});
4525            auto sem_val = s.sem();
4526            // std(ddof=1) = sqrt(2.5), sem = sqrt(2.5)/sqrt(5) ≈ 0.707
4527            bool passed = sem_val.has_value() && std::abs(*sem_val - 0.707) < 0.01;
4528            if (!passed) {
4529                std::cout << "  [FAIL] : in pd_test_aggregation_series_sem() : sem value incorrect" << std::endl;
4530                throw std::runtime_error("pd_test_aggregation_series_sem failed: sem value incorrect");
4531            }
4532
4533            std::cout << " -> tests passed" << std::endl;
4534        }
skew (pd_test_1_all.cpp:4592)
4582                throw std::runtime_error("pd_test_aggregation_series_mode failed: multi-mode should return 2 values");
4583            }
4584
4585            std::cout << " -> tests passed" << std::endl;
4586        }
4587
4588        void pd_test_aggregation_series_skew_kurt() {
4589            std::cout << "========= Series skew/kurt ======================";
4590
4591            pandas::Series<double> s({1.0, 2.0, 2.0, 3.0, 9.0});
4592            auto skew_val = s.skew();
4593            bool passed = skew_val.has_value() && *skew_val > 0;  // Should be right-skewed
4594            if (!passed) {
4595                std::cout << "  [FAIL] : in pd_test_aggregation_series_skew_kurt() : skew should be positive" << std::endl;
4596                throw std::runtime_error("pd_test_aggregation_series_skew_kurt failed: skew should be positive");
4597            }
4598
4599            auto kurt_val = s.kurt();
4600            passed = kurt_val.has_value();
4601            if (!passed) {
4602                std::cout << "  [FAIL] : in pd_test_aggregation_series_skew_kurt() : kurt should have value" << std::endl;
std_ (pd_test_1_all.cpp:20752)
20742                throw std::runtime_error("pd_test_rolling_min_periods failed: with min_periods=1, idx 1 should be 3.0");
20743            }
20744
20745            std::cout << " -> tests passed" << std::endl;
20746        }
20747
20748        void pd_test_rolling_std() {
20749            std::cout << "========= Rolling std ===========================";
20750
20751            pandas::Series<double> s({1.0, 2.0, 3.0, 4.0, 5.0});
20752            auto result = s.rolling(3).std_();
20753
20754            // std([1,2,3]) = 1.0 (ddof=1)
20755            // std([2,3,4]) = 1.0
20756            // std([3,4,5]) = 1.0
20757            bool passed = std::abs(result[2] - 1.0) < 0.001;
20758            if (!passed) {
20759                std::cout << "  [FAIL] : in pd_test_rolling_std() : rolling std should be 1.0" << std::endl;
20760                throw std::runtime_error("pd_test_rolling_std failed: rolling std should be 1.0");
20761            }
sum (pd_test_1_all.cpp:276)
266        }
267
268        // Test sum/mean
269        pandas::BooleanArray arr({
270            std::optional<bool>(true),
271            std::optional<bool>(false),
272            std::optional<bool>(true),
273            std::optional<bool>(true)
274        });
275
276        auto s = arr.sum();
277        if (!s.has_value() || s.value() != 3) {
278            std::cout << "  [FAIL] : in pd_test_boolean_array_reductions() : sum should be 3" << std::endl;
279            throw std::runtime_error("pd_test_boolean_array_reductions failed: sum");
280        }
281
282        auto m = arr.mean();
283        if (!m.has_value() || std::abs(m.value() - 0.75) > 0.001) {
284            std::cout << "  [FAIL] : in pd_test_boolean_array_reductions() : mean should be 0.75" << std::endl;
285            throw std::runtime_error("pd_test_boolean_array_reductions failed: mean");
286        }
var (pd_test_1_all.cpp:20890)
20880                throw std::runtime_error("pd_test_expanding_std failed: expanding std values incorrect");
20881            }
20882
20883            std::cout << " -> tests passed" << std::endl;
20884        }
20885
20886        void pd_test_expanding_var() {
20887            std::cout << "========= Expanding var =========================";
20888
20889            pandas::Series<double> s({1.0, 2.0, 3.0, 4.0, 5.0});
20890            auto result = s.expanding().var();
20891
20892            // Expanding var (ddof=1): NaN, 0.5, 1.0, 1.6667, 2.5
20893            bool passed = std::isnan(result[0]) &&
20894                          std::abs(result[1] - 0.5) < 0.001 &&
20895                          std::abs(result[2] - 1.0) < 0.001 &&
20896                          std::abs(result[3] - 1.6667) < 0.001 &&
20897                          std::abs(result[4] - 2.5) < 0.001;
20898            if (!passed) {
20899                std::cout << "  [FAIL] : in pd_test_expanding_var() : expanding var values incorrect" << std::endl;
20900                throw std::runtime_error("pd_test_expanding_var failed: expanding var values incorrect");
apply (pd_test_1_all.cpp:11244)
11234        void pd_test_func_apply_dataframe_apply_axis0() {
11235            std::cout << "========= DataFrame apply axis=0 ======================";
11236
11237            std::map<std::string, std::vector<double>> data = {
11238                {"A", {1.0, 2.0, 3.0}},
11239                {"B", {4.0, 5.0, 6.0}}
11240            };
11241            pandas::DataFrame df(data);
11242
11243            // apply axis=0 applies function to each column
11244            auto result = df.apply([](const std::vector<double>& col) {
11245                return std::accumulate(col.begin(), col.end(), 0.0);
11246            }, 0);
11247
11248            bool passed = true;
11249
11250            // Plan F·dtype: axis=0 reduce now returns a single "result" column
11251            // with the original column names ("A", "B") as the row index.
11252            // Sum of A: 1+2+3=6, Sum of B: 4+5+6=15
11253            const auto& result_col = result["result"];
11254            double sum_a = std::stod(result_col.get_value_str(0));
rank (pd_test_1_all.cpp:6451)
6441        // =====================================================================
6442        // Test: Rank
6443        // =====================================================================
6444        void pd_test_dataframe_rank() {
6445            std::cout << "========= rank =============================";
6446
6447            // Test Series rank with default method (average)
6448            {
6449                std::vector<double> data = {3.0, 1.0, 4.0, 1.0, 5.0};
6450                pandas::Series<double> s(data, "test");
6451                auto ranked = s.rank();
6452
6453                // Values: 3, 1, 4, 1, 5 -> Sorted: 1, 1, 3, 4, 5
6454                // Ranks (average): 1.5, 1.5, 3, 4, 5
6455                // Original positions: 3->3, 1->1.5, 4->4, 1->1.5, 5->5
6456                double r0 = std::stod(ranked.get_value_str(0));  // 3.0 -> rank 3
6457                double r1 = std::stod(ranked.get_value_str(1));  // 1.0 -> rank 1.5
6458
6459                if (std::abs(r0 - 3.0) > 1e-10) {
6460                    std::cout << "  [FAIL] : in pd_test_dataframe_rank() : value 3.0 should have rank 3, got " << r0 << std::endl;
6461                    throw std::runtime_error("pd_test_dataframe_rank failed: value 3.0 rank");
is_time_based (pd_test_3_all.cpp:24693)
24683        numpy::datetime64("2023-01-01"),
24684        numpy::datetime64("2023-01-02"),
24685        numpy::datetime64("2023-01-03"),
24686        numpy::datetime64("2023-01-04"),
24687        numpy::datetime64("2023-01-05")
24688    };
24689    auto dti = std::make_unique<pandas::DatetimeIndex>(dates);
24690    pandas::Series<double> s({1.0, 2.0, 3.0, 4.0, 5.0});
24691    s.set_index(std::move(dti));
24692    auto rolling = pandas::setup_time_rolling(s, "3D", "right", 1);
24693    if (!rolling.is_time_based())
24694        throw std::runtime_error("expected time-based rolling");
24695    std::cout << " -> tests passed" << std::endl;
24696}
24697
24698void pd_test_rolling_time_no_dti() {
24699    std::cout << "========= setup_time_rolling no DTI =================";
24700    // Series without DatetimeIndex should throw
24701    pandas::Series<double> s({1.0, 2.0, 3.0});
24702    bool threw = false;
24703    try {
corr (pd_test_1_all.cpp:4655)
4645        }
4646
4647        void pd_test_aggregation_dataframe_corr() {
4648            std::cout << "========= DataFrame corr ========================";
4649
4650            std::map<std::string, std::vector<double>> data;
4651            data["A"] = {1.0, 2.0, 3.0, 4.0, 5.0};
4652            data["B"] = {2.0, 4.0, 6.0, 8.0, 10.0};  // Perfect correlation
4653            pandas::DataFrame df(data);
4654
4655            auto corr_df = df.corr();
4656
4657            // Check dimensions
4658            bool passed = corr_df.nrows() == 2 && corr_df.ncols() == 2;
4659            if (!passed) {
4660                std::cout << "  [FAIL] : in pd_test_aggregation_dataframe_corr() : corr should be 2x2" << std::endl;
4661                throw std::runtime_error("pd_test_aggregation_dataframe_corr failed: corr should be 2x2");
4662            }
4663
4664            // Diagonal should be 1.0
4665            std::string aa = corr_df["A"].get_value_str(0);
cov (pd_test_1_all.cpp:4690)
4680            std::cout << " -> tests passed" << std::endl;
4681        }
4682
4683        void pd_test_aggregation_dataframe_cov() {
4684            std::cout << "========= DataFrame cov =========================";
4685
4686            std::map<std::string, std::vector<double>> data;
4687            data["A"] = {1.0, 2.0, 3.0};
4688            pandas::DataFrame df(data);
4689
4690            auto cov_df = df.cov();
4691
4692            // Check dimensions
4693            bool passed = cov_df.nrows() == 1 && cov_df.ncols() == 1;
4694            if (!passed) {
4695                std::cout << "  [FAIL] : in pd_test_aggregation_dataframe_cov() : cov should be 1x1" << std::endl;
4696                throw std::runtime_error("pd_test_aggregation_dataframe_cov failed: cov should be 1x1");
4697            }
4698
4699            // Var(A) = 1.0 with ddof=1
4700            std::string aa = cov_df["A"].get_value_str(0);