Grouper ======= .. cpp:class:: pandas::Grouper pandas C++ class. Example ------- .. code-block:: cpp #include using namespace pandas; // Use Grouper Grouper obj; // ... operations ... Constructors ------------ .. list-table:: :widths: 55 25 20 :header-rows: 1 * - Signature - Location - Example * - ``Grouper() = default`` - pd_grouper.h:32 - :ref:`View ` * - ``explicit Grouper(const std::string& key)`` - pd_grouper.h:35 - :ref:`View ` * - ``explicit Grouper( std::optional key, std::optional> level, std::optional freq = std::nullopt, int axis = 0, bool sort = false, std::optional closed = std::nullopt, std::optional label = std::nullopt, std::optional convention = std::nullopt, const std::string& origin = "start_day", std::optional offset = std::nullopt, bool dropna = true)`` - pd_grouper.h:39 - :ref:`View ` Construction ------------ .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``static Grouper from_freq(const std::string& f)`` - static Grouper - pd_grouper.h:88 - :ref:`View ` Data Manipulation ----------------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``bool dropna() const`` - bool - pd_grouper.h:66 - :ref:`View ` * - ``Grouper& set_axis(int axis)`` - Grouper& - pd_grouper.h:99 - :ref:`View ` Comparison ---------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``std::optional> level() const`` - std::optional> - pd_grouper.h:57 - :ref:`View ` Type Checking ------------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``bool is_time_grouper() const`` - bool - pd_grouper.h:69 - :ref:`View ` Other Methods ------------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``int axis() const`` - int - pd_grouper.h:59 - :ref:`View ` * - ``std::optional closed() const`` - std::optional - pd_grouper.h:61 - :ref:`View ` * - ``std::optional convention() const`` - std::optional - pd_grouper.h:63 - :ref:`View ` * - ``std::optional freq() const`` - std::optional - pd_grouper.h:58 - :ref:`View ` * - ``static Grouper freq_key(const std::string& freq, const std::string& key)`` - static Grouper - pd_grouper.h:79 - :ref:`View ` * - ``std::optional key() const`` - std::optional - pd_grouper.h:56 - :ref:`View ` * - ``std::optional label() const`` - std::optional - pd_grouper.h:62 - :ref:`View ` * - ``std::optional offset() const`` - std::optional - pd_grouper.h:65 - :ref:`View ` * - ``std::string origin() const`` - std::string - pd_grouper.h:64 - :ref:`View ` * - ``Grouper& set_closed(const std::string& closed)`` - Grouper& - pd_grouper.h:101 - :ref:`View ` * - ``Grouper& set_convention(const std::string& convention)`` - Grouper& - pd_grouper.h:103 - * - ``Grouper& set_dropna(bool dropna)`` - Grouper& - pd_grouper.h:106 - :ref:`View ` * - ``Grouper& set_freq(const std::string& freq)`` - Grouper& - pd_grouper.h:98 - :ref:`View ` * - ``Grouper& set_key(const std::string& key)`` - Grouper& - pd_grouper.h:95 - :ref:`View ` * - ``Grouper& set_label(const std::string& label)`` - Grouper& - pd_grouper.h:102 - * - ``Grouper& set_level(int level)`` - Grouper& - pd_grouper.h:96 - :ref:`View ` * - ``Grouper& set_level(const std::string& level)`` - Grouper& - pd_grouper.h:97 - :ref:`View ` * - ``Grouper& set_offset(const std::string& offset)`` - Grouper& - pd_grouper.h:105 - * - ``Grouper& set_origin(const std::string& origin)`` - Grouper& - pd_grouper.h:104 - * - ``Grouper& set_sort(bool sort)`` - Grouper& - pd_grouper.h:100 - :ref:`View ` * - ``bool sort() const`` - bool - pd_grouper.h:60 - :ref:`View ` Code Examples ------------- The following examples are extracted from the test suite. .. _example-grouper-grouper-0: .. dropdown:: Grouper (pd_test_4_all.cpp:5041) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 5031 :emphasize-lines: 11 "0 True 1.1 10.0 1.0 x\n" "1 False 2.2 20.0 2.0 y\n" "2 True 3.3 30.0 3.0 z\n" "3 NaN NaN NaN NaN NaN\n" "4 NaN NaN NaN NaN NaN"; check_str("reindex_types_default_nan", expected, re.to_string()); } // ============================================================================ // Group C — `__freq_idx__` synthetic name leak in groupby(Grouper(freq=...)) // Source: pandasPython_tests/test_anal_grouper_freq_level_compare_full.py // // All 7 cases share the same shape: DatetimeIndex (quarter-end) + 2 int // columns. PandasCore's groupby leaves the synthetic index name // "__freq_idx__" on the result, and the formatter dutifully prints it. // pandas hides this entirely. We reproduce by constructing the *result* // DataFrame directly with the leaky index name — fix paths: either groupby // must clear the name, or the formatter must blacklist names beginning with // "__freq_idx__" / leading underscores from synthetic groupers. // ============================================================================ .. _example-grouper-grouper-1: .. dropdown:: Grouper (pd_test_4_all.cpp:5041) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 5031 :emphasize-lines: 11 "0 True 1.1 10.0 1.0 x\n" "1 False 2.2 20.0 2.0 y\n" "2 True 3.3 30.0 3.0 z\n" "3 NaN NaN NaN NaN NaN\n" "4 NaN NaN NaN NaN NaN"; check_str("reindex_types_default_nan", expected, re.to_string()); } // ============================================================================ // Group C — `__freq_idx__` synthetic name leak in groupby(Grouper(freq=...)) // Source: pandasPython_tests/test_anal_grouper_freq_level_compare_full.py // // All 7 cases share the same shape: DatetimeIndex (quarter-end) + 2 int // columns. PandasCore's groupby leaves the synthetic index name // "__freq_idx__" on the result, and the formatter dutifully prints it. // pandas hides this entirely. We reproduce by constructing the *result* // DataFrame directly with the leaky index name — fix paths: either groupby // must clear the name, or the formatter must blacklist names beginning with // "__freq_idx__" / leading underscores from synthetic groupers. // ============================================================================ .. _example-grouper-grouper-2: .. dropdown:: Grouper (pd_test_4_all.cpp:5041) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 5031 :emphasize-lines: 11 "0 True 1.1 10.0 1.0 x\n" "1 False 2.2 20.0 2.0 y\n" "2 True 3.3 30.0 3.0 z\n" "3 NaN NaN NaN NaN NaN\n" "4 NaN NaN NaN NaN NaN"; check_str("reindex_types_default_nan", expected, re.to_string()); } // ============================================================================ // Group C — `__freq_idx__` synthetic name leak in groupby(Grouper(freq=...)) // Source: pandasPython_tests/test_anal_grouper_freq_level_compare_full.py // // All 7 cases share the same shape: DatetimeIndex (quarter-end) + 2 int // columns. PandasCore's groupby leaves the synthetic index name // "__freq_idx__" on the result, and the formatter dutifully prints it. // pandas hides this entirely. We reproduce by constructing the *result* // DataFrame directly with the leaky index name — fix paths: either groupby // must clear the name, or the formatter must blacklist names beginning with // "__freq_idx__" / leading underscores from synthetic groupers. // ============================================================================ .. _example-grouper-from_freq-3: .. dropdown:: from_freq (pd_test_5_all.cpp:352) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 342 :emphasize-lines: 11 int local_fail = 0; // 12 monthly dates starting 2020-01-01 pandas::DatetimeIndex dt_idx("2020-01-01", 12, "ME"); pandas::DataFrame df; df.set_index(dt_idx); std::vector amounts = {100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200}; std::vector counts(12, 1); df.add_column("Amount", amounts); df.add_column("Count", counts); auto result = df.groupby(pandas::Grouper::from_freq("QE")).sum(); std::string expected = " Amount Count\n" "2020-03-31 600 3\n" "2020-06-30 1500 3\n" "2020-09-30 2400 3\n" "2020-12-31 3300 3"; pandas_tests::check(result.to_string() == expected, "grouper_freq_dtindex.str", local_fail); if (local_fail > 0) { std::cout << " [FAIL] : in f_test_anal_grouper_freq_level_compare_full_175() : " << local_fail << " checks failed" << std::endl; .. _example-grouper-dropna-4: .. dropdown:: dropna (pd_test_1_all.cpp:531) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 521 :emphasize-lines: 11 } // Test isna array numpy::NDArray na_mask = arr.isna(); if (na_mask.getSize() != 4) { std::cout << " [FAIL] : in pd_test_categorical_array_na_handling() : isna size != 4" << std::endl; throw std::runtime_error("pd_test_categorical_array_na_handling failed: isna size != 4"); } // Test dropna pandas::CategoricalArray dropped = arr.dropna(); if (dropped.size() != 2) { std::cout << " [FAIL] : in pd_test_categorical_array_na_handling() : dropna size != 2" << std::endl; throw std::runtime_error("pd_test_categorical_array_na_handling failed: dropna size != 2"); } // Test fillna (fill with existing category) pandas::CategoricalArray filled = arr.fillna("a"); // 'a' is in categories if (filled.has_na()) { std::cout << " [FAIL] : in pd_test_categorical_array_na_handling() : fillna should have no NA" << std::endl; throw std::runtime_error("pd_test_categorical_array_na_handling failed: fillna should have no NA"); .. _example-grouper-set_axis-5: .. dropdown:: set_axis (pd_test_1_all.cpp:6673) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 6663 :emphasize-lines: 11 std::cout << " -> tests passed" << std::endl; } // ===================================================================== // Test: Index Operations // ===================================================================== void pd_test_dataframe_index_ops() { std::cout << "========= index operations ================="; // Test set_axis (rows) { std::map> data; data["A"] = {1, 2, 3}; pandas::DataFrame df(data); auto renamed = df.set_axis({"x", "y", "z"}, 0); std::string idx0 = renamed.index().get_value_str(0); if (idx0 != "x") { std::cout << " [FAIL] : in pd_test_dataframe_index_ops() : set_axis first label should be 'x'" << std::endl; throw std::runtime_error("pd_test_dataframe_index_ops failed: set_axis"); .. _example-grouper-level-6: .. dropdown:: level (pd_test_2_all.cpp:10027) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 10017 :emphasize-lines: 11 std::cout << " [FAIL] : in pd_test_swaplevel_negative_indices() : wrong index values" << std::endl; std::cout << " Expected: C:B:A, F:E:D" << std::endl; std::cout << " Got: " << idx0 << ", " << idx1 << std::endl; throw std::runtime_error("pd_test_swaplevel_negative_indices failed"); } std::cout << " -> tests passed" << std::endl; } void pd_test_swaplevel_same_level() { std::cout << "========= swaplevel same level (no change) ============="; std::map> data = { {"value", {"a", "b"}} }; pandas::DataFrame df(data); std::vector hier_index = {"X:Y:Z", "A:B:C"}; df.set_index(std::make_unique>(hier_index)); .. _example-grouper-is_time_grouper-7: .. dropdown:: is_time_grouper (pd_test_3_all.cpp:19042) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 19032 :emphasize-lines: 11 throw std::runtime_error("pd_test_grouper_builder: freq failed"); } if (g.sort()) { std::cout << " [FAIL] : builder sort failed" << std::endl; throw std::runtime_error("pd_test_grouper_builder: sort failed"); } if (g.dropna()) { std::cout << " [FAIL] : builder dropna failed" << std::endl; throw std::runtime_error("pd_test_grouper_builder: dropna failed"); } if (!g.is_time_grouper()) { std::cout << " [FAIL] : is_time_grouper failed" << std::endl; throw std::runtime_error("pd_test_grouper_builder: is_time_grouper failed"); } std::cout << " -> tests passed" << std::endl; } // ============================================================================ // Test Grouper full constructor // ============================================================================ .. _example-grouper-axis-8: .. dropdown:: axis (pd_test_1_all.cpp:25083) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 25073 :emphasize-lines: 11 } if (!passed) { throw std::runtime_error("pd_test_median_empty_column failed"); } std::cout << " -> tests passed" << std::endl; } void pd_test_median_invalid_axis() { std::cout << "========= median invalid axis (throws exception) ================="; std::map> data; data["A"] = {1.0, 2.0, 3.0}; pandas::DataFrame df(data); bool passed = false; try { df.median(2); // Invalid axis } catch (const std::exception&) { .. _example-grouper-closed-9: .. dropdown:: closed (pd_test_1_all.cpp:1903) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1893 :emphasize-lines: 11 // ============================================================================ void test_constructors() { std::cout << "========= IntervalArray: constructors ======================= "; // Default constructor pandas::IntervalArrayFloat64 empty; if (empty.size() != 0) { std::cout << "[FAIL] : in test_constructors() : default constructor size" << std::endl; return; } if (empty.closed() != pandas::IntervalClosed::Right) { std::cout << "[FAIL] : in test_constructors() : default closure" << std::endl; return; } // Constructor from left/right arrays numpy::NDArray left(std::vector{3}); numpy::NDArray right(std::vector{3}); left.setElementAt({0}, 0.0); right.setElementAt({0}, 1.0); left.setElementAt({1}, 1.0); right.setElementAt({1}, 2.0); left.setElementAt({2}, 2.0); right.setElementAt({2}, 3.0); .. _example-grouper-convention-10: .. dropdown:: convention (pd_test_5_all.cpp:67797) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 67787 :emphasize-lines: 11 std::cout << "-- case_30_agg_var_passlock\n"; auto s = make_carrier({1.0, 2.0, 3.0}, "UInt8"); auto v = s.agg("var"); pandas_tests::check(opt_equals(v, 1.0, "case_30.agg_var_value"), "case_30.agg_var_eq_1", local_fail); } void f_series_uint_sum_agg_typed_9_4791556_case_31_empty_uint8_sum_value(int& local_fail) { std::cout << "-- case_31_empty_uint8_sum_value\n"; // empty UInt8: sum() returns optional(0.0) per pandas // convention (identity element). Binding stamps uint32(0). auto s = make_carrier({}, "UInt8"); auto v = s.sum(); pandas_tests::check(opt_equals(v, 0.0, "case_31.empty_sum_value"), "case_31.empty_sum_eq_0", local_fail); } void f_series_uint_sum_agg_typed_9_4791556_case_32_empty_uint8_prod_value(int& local_fail) { std::cout << "-- case_32_empty_uint8_prod_value\n"; // empty UInt8 prod -> 1 (multiplicative identity). Binding stamps // uint32(1). .. _example-grouper-freq-11: .. dropdown:: freq (pd_test_1_all.cpp:8233) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 8223 :emphasize-lines: 11 std::cout << "========= freq property ==============================="; std::vector> values = { numpy::datetime64(0LL, numpy::DateTimeUnit::Nanosecond), numpy::datetime64(86400000000000LL, numpy::DateTimeUnit::Nanosecond) // 1 day }; pandas::DatetimeArray arr(values); pandas::DatetimeMixinIndex idx(arr); // Default freq is nullopt or inferred auto f = idx.freq(); std::string fs = idx.freqstr(); bool passed = true; // freq may or may not be set if (!passed) { std::cout << " [FAIL] : in pd_test_datetime_mixin_freq()" << std::endl; throw std::runtime_error("pd_test_datetime_mixin_freq failed"); } std::cout << " -> tests passed" << std::endl; } .. _example-grouper-freq_key-12: .. dropdown:: freq_key (pd_test_3_all.cpp:11083) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 11073 :emphasize-lines: 11 void pd_test_3_all_groupby_mixed() { std::cout << "========= groupby(mixed Grouper+string) ================"; pandas::DataFrame df; df.add_column("Buyer", {"Alice","Bob","Alice","Bob"}); df.add_column("Amount", {100.0, 200.0, 150.0, 250.0}); auto dates = pandas::date_range("2024-01-15", 4, "15D"); df.set_index(std::make_shared(dates)); df.add_column("Date_str", {"2024-01-15","2024-01-30","2024-02-14","2024-03-01"}); auto result = df.groupby( {pandas::Grouper::freq_key("1ME", "Date_str"), std::string("Buyer")}).sum(); if (result.nrows() < 2) { std::cout << " [FAIL] : in pd_test_3_all_groupby_mixed()" << std::endl; throw std::runtime_error("groupby mixed failed"); } std::cout << " -> tests passed" << std::endl; } void pd_test_3_all_ndframebase_unstack() { std::cout << "========= NDFrameBase.unstack() ========================"; auto mi = pandas::MultiIndex::from_arrays( .. _example-grouper-key-13: .. dropdown:: key (pd_test_2_all.cpp:11898) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 11888 :emphasize-lines: 11 if (!threw) { std::cout << " [FAIL] : should have thrown" << std::endl; throw std::runtime_error("pd_test_to_hdf_invalid_mode failed"); } std::cout << " -> tests passed" << std::endl; } void pd_test_to_hdf_empty_key() { std::cout << "========= to_hdf empty key (real HDF5) ========================="; std::map> data = {{"col", {1.0, 2.0, 3.0}}}; pandas::DataFrame df(data); bool threw = false; try { df.to_hdf("temp/test.h5", ""); } catch (const std::exception& e) { threw = true; std::string msg = e.what(); .. _example-grouper-label-14: .. dropdown:: label (pd_test_4_all.cpp:4935) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 4925 :emphasize-lines: 11 // Helper: compare and report // ---------------------------------------------------------------------------- static void check_str(const std::string& label, const std::string& expected, const std::string& actual) { int _f = 0; pandas_tests::check_str_ws(label, expected, actual, _f); if (_f > 0) throw std::runtime_error(label + ": str mismatch"); } // Slugify a python compare-test label ("a.b.c" → "a_b_c") matching the // scheme in scripts/gen_repr_mismatch_fixtures.py. static std::string slugify_label(const std::string& label) { std::string out = label; for (char& ch : out) { if (ch == '.') ch = '_'; } return out; } // Load a captured pandas-generated expected output file. The file is written .. _example-grouper-offset-15: .. dropdown:: offset (pd_test_3_all.cpp:18224) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 18214 :emphasize-lines: 11 namespace dataframe_tests { namespace dataframe_tests_dateoffset { // ============================================================================ // Test Day offset // ============================================================================ void pd_test_day_offset() { std::cout << "========= Day offset ==================================="; pandas::Day offset(5); if (offset.n() != 5) { std::cout << " [FAIL] : Day n() failed" << std::endl; throw std::runtime_error("pd_test_day_offset: n() failed"); } if (offset.freqstr() != "D") { std::cout << " [FAIL] : Day freqstr() failed" << std::endl; throw std::runtime_error("pd_test_day_offset: freqstr() failed"); } if (offset.name() != "Day") { std::cout << " [FAIL] : Day name() failed" << std::endl; .. _example-grouper-origin-16: .. dropdown:: origin (pd_test_2_all.cpp:22665) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22655 :emphasize-lines: 11 pandas::Timestamp ts(v->getValue()); check(ts.year() == 1970, "year==1970"); check(ts.month() == 1, "month==1"); check(ts.day() == 2, "day==2"); } } void test_to_datetime_numeric_origin() { std::cout << " -- test_to_datetime_numeric_origin --" << std::endl; // origin = 2000-01-01, values = [1, 2, 3] days pandas::Timestamp origin(2000, 1, 1, 0, 0, 0, 0, 0, ""); int64_t origin_ns = origin.value(); std::vector vals = {1.0, 2.0, 3.0}; auto arr = pandas::to_datetime_numeric(vals, "D", origin_ns); check(arr.size() == 3, "size==3"); // Day 1 from 2000-01-01 = 2000-01-02 auto v0 = arr[0]; check(v0.has_value(), "v0_has_value"); if (v0.has_value()) { pandas::Timestamp ts(v0->getValue()); .. _example-grouper-set_closed-17: .. dropdown:: set_closed (pd_test_1_all.cpp:2285) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 2275 :emphasize-lines: 11 std::vector breaks = {0.0, 1.0, 2.0}; auto arr = pandas::IntervalArrayFloat64::from_breaks(breaks, pandas::IntervalClosed::Right); if (arr.closed() != pandas::IntervalClosed::Right) { std::cout << "[FAIL] : in test_set_closed() : initial closure" << std::endl; return; } // Change to left-closed auto arr_left = arr.set_closed(pandas::IntervalClosed::Left); if (arr_left.closed() != pandas::IntervalClosed::Left) { std::cout << "[FAIL] : in test_set_closed() : set to Left" << std::endl; return; } // Original should be unchanged if (arr.closed() != pandas::IntervalClosed::Right) { std::cout << "[FAIL] : in test_set_closed() : original changed" << std::endl; return; } .. _example-grouper-set_dropna-18: .. dropdown:: set_dropna (pd_test_3_all.cpp:19024) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 19014 :emphasize-lines: 11 } // ============================================================================ // Test Grouper builder pattern // ============================================================================ void pd_test_grouper_builder() { std::cout << "========= Grouper: builder pattern ========================="; pandas::Grouper g; g.set_key("A").set_freq("M").set_sort(false).set_dropna(false); if (g.key().value() != "A") { std::cout << " [FAIL] : builder key failed" << std::endl; throw std::runtime_error("pd_test_grouper_builder: key failed"); } if (g.freq().value() != "M") { std::cout << " [FAIL] : builder freq failed" << std::endl; throw std::runtime_error("pd_test_grouper_builder: freq failed"); } if (g.sort()) { .. _example-grouper-set_freq-19: .. dropdown:: set_freq (pd_test_1_all.cpp:8254) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 8244 :emphasize-lines: 11 void pd_test_datetime_mixin_set_freq() { std::cout << "========= set_freq ===================================="; std::vector> values = { numpy::datetime64(0LL, numpy::DateTimeUnit::Nanosecond) }; pandas::DatetimeArray arr(values); pandas::DatetimeMixinIndex idx(arr); idx.set_freq("D"); auto f = idx.freq(); bool passed = (f.has_value() && *f == "D"); if (!passed) { std::cout << " [FAIL] : in pd_test_datetime_mixin_set_freq()" << std::endl; throw std::runtime_error("pd_test_datetime_mixin_set_freq failed"); } std::cout << " -> tests passed" << std::endl; } .. _example-grouper-set_key-20: .. dropdown:: set_key (pd_test_3_all.cpp:19024) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 19014 :emphasize-lines: 11 } // ============================================================================ // Test Grouper builder pattern // ============================================================================ void pd_test_grouper_builder() { std::cout << "========= Grouper: builder pattern ========================="; pandas::Grouper g; g.set_key("A").set_freq("M").set_sort(false).set_dropna(false); if (g.key().value() != "A") { std::cout << " [FAIL] : builder key failed" << std::endl; throw std::runtime_error("pd_test_grouper_builder: key failed"); } if (g.freq().value() != "M") { std::cout << " [FAIL] : builder freq failed" << std::endl; throw std::runtime_error("pd_test_grouper_builder: freq failed"); } if (g.sort()) { .. _example-grouper-set_level-21: .. dropdown:: set_level (pd_test_5_all.cpp:21141) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 21131 :emphasize-lines: 11 "case7.index_name_is_date"), "case7.index_name_is_date", local_fail); pandas_tests::check(str_eq(result.to_string(), expected, "case7.to_string"), "case7.to_string_matches_pandas", local_fail); } void f_grouper_freq_key_col_index_name_742013_case_8_named_dtindex_level0_QE(int& local_fail) { std::cout << "-- f_grouper_freq_key_col_index_name_742013_case_8_named_dtindex_level0_QE\n"; auto df = make_df_named_dtindex_as_index(); pandas::Grouper g; g.set_level(0).set_freq("QE"); auto result = df.groupby(g).sum(); std::string expected = " Amount Count\n" "dtidx \n" "2020-03-31 600 3\n" "2020-06-30 1500 3\n" "2020-09-30 2400 3\n" "2020-12-31 3300 3"; pandas_tests::check(opt_eq(result.index_name(), std::optional("dtidx"), .. _example-grouper-set_level-22: .. dropdown:: set_level (pd_test_5_all.cpp:21141) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 21131 :emphasize-lines: 11 "case7.index_name_is_date"), "case7.index_name_is_date", local_fail); pandas_tests::check(str_eq(result.to_string(), expected, "case7.to_string"), "case7.to_string_matches_pandas", local_fail); } void f_grouper_freq_key_col_index_name_742013_case_8_named_dtindex_level0_QE(int& local_fail) { std::cout << "-- f_grouper_freq_key_col_index_name_742013_case_8_named_dtindex_level0_QE\n"; auto df = make_df_named_dtindex_as_index(); pandas::Grouper g; g.set_level(0).set_freq("QE"); auto result = df.groupby(g).sum(); std::string expected = " Amount Count\n" "dtidx \n" "2020-03-31 600 3\n" "2020-06-30 1500 3\n" "2020-09-30 2400 3\n" "2020-12-31 3300 3"; pandas_tests::check(opt_eq(result.index_name(), std::optional("dtidx"), .. _example-grouper-set_sort-23: .. dropdown:: set_sort (pd_test_3_all.cpp:19024) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 19014 :emphasize-lines: 11 } // ============================================================================ // Test Grouper builder pattern // ============================================================================ void pd_test_grouper_builder() { std::cout << "========= Grouper: builder pattern ========================="; pandas::Grouper g; g.set_key("A").set_freq("M").set_sort(false).set_dropna(false); if (g.key().value() != "A") { std::cout << " [FAIL] : builder key failed" << std::endl; throw std::runtime_error("pd_test_grouper_builder: key failed"); } if (g.freq().value() != "M") { std::cout << " [FAIL] : builder freq failed" << std::endl; throw std::runtime_error("pd_test_grouper_builder: freq failed"); } if (g.sort()) { .. _example-grouper-sort-24: .. dropdown:: sort (pd_test_3_all.cpp:3869) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 3859 :emphasize-lines: 11 throw std::runtime_error("last 2 positions should be NaN"); } if (std::abs(result[0] - 3.0) > 0.001) { throw std::runtime_error("shift(-2) [0] should be 3.0"); } std::cout << " -> tests passed" << std::endl; } void pd_test_3_all_index_sort() { std::cout << "========= Index.sort() ============================="; pandas::Index idx({3, 1, 4, 1, 5, 9, 2, 6}); auto result = idx.sort(); if (result[0] != 1 || result[1] != 1 || result[7] != 9) { throw std::runtime_error("sort() not working correctly"); } // Test descending result = idx.sort(false);