StringArray =========== .. cpp:class:: pandas::StringArray Extension array type for specialized data storage. Example ------- .. code-block:: cpp #include using namespace pandas; // Use StringArray StringArray obj; // ... operations ... Constructors ------------ .. list-table:: :widths: 55 25 20 :header-rows: 1 * - Signature - Location - Example * - ``StringArray(const numpy::NDArray& data, const numpy::NDArray& mask, bool copy = false)`` - pd_string_array.h:71 - * - ``explicit StringArray(const numpy::NDArray& data)`` - pd_string_array.h:84 - * - ``explicit StringArray(const std::vector>& values)`` - pd_string_array.h:115 - * - ``explicit StringArray(const std::vector& values)`` - pd_string_array.h:133 - Construction ------------ .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``static StringArray from_sequence(const std::vector>& scalars)`` - static StringArray - pd_string_array.h:330 - Indexing / Selection -------------------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``std::string at(size_t index) const`` - std::string - pd_string_array.h:230 - :ref:`View ` * - ``const numpy::NDArray& mask() const`` - const numpy::NDArray& - pd_string_array.h:210 - :ref:`View ` * - ``StringArray take(const std::vector& indices, bool allow_fill = false, std::optional fill_value = std::nullopt) const`` - StringArray - pd_string_array.h:277 - :ref:`View ` Data Manipulation ----------------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``StringArray dropna() const`` - StringArray - pd_string_array.h:380 - :ref:`View ` Missing Data ------------ .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``StringArray fillna(const std::string& value) const`` - StringArray - pd_string_array.h:366 - :ref:`View ` * - ``numpy::NDArray isna() const`` - numpy::NDArray - pd_string_array.h:252 - :ref:`View ` * - ``numpy::NDArray notna() const`` - numpy::NDArray - pd_string_array.h:259 - :ref:`View ` Statistics ---------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``size_t count() const`` - size_t - pd_string_array.h:411 - :ref:`View ` Comparison ---------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``size_t len() const`` - size_t - pd_string_array.h:192 - :ref:`View ` Sorting ------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``numpy::NDArray argsort(bool ascending = true, const std::string& na_position = "last") const`` - numpy::NDArray - pd_string_array.h:702 - :ref:`View ` Combining --------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``static StringArray concat(const std::vector& arrays)`` - static StringArray - pd_string_array.h:337 - :ref:`View ` I/O --- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``numpy::NDArray to_numpy(bool copy = true, U na_value = U{}) const`` - numpy::NDArray - pd_string_array.h:394 - :ref:`View ` * - ``std::string to_string() const`` - std::string - pd_string_array.h:1138 - :ref:`View ` Conversion ---------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``StringArray copy() const`` - StringArray - pd_string_array.h:270 - :ref:`View ` Set Operations -------------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``StringArray unique() const`` - StringArray - pd_string_array.h:635 - :ref:`View ` Type Checking ------------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``bool is_na(size_t index) const`` - bool - pd_string_array.h:241 - :ref:`View ` Other Methods ------------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``std::optional all(bool skipna = true) const`` - std::optional - pd_string_array.h:1087 - :ref:`View ` * - ``std::optional any(bool skipna = true) const`` - std::optional - pd_string_array.h:1060 - :ref:`View ` * - ``std::optional argmax() const`` - std::optional - pd_string_array.h:755 - :ref:`View ` * - ``std::optional argmin() const`` - std::optional - pd_string_array.h:734 - :ref:`View ` * - ``const numpy::NDArray& data() const`` - const numpy::NDArray& - pd_string_array.h:203 - :ref:`View ` * - ``dtype_type dtype() const`` - dtype_type - pd_string_array.h:150 - :ref:`View ` * - ``bool empty() const`` - bool - pd_string_array.h:185 - :ref:`View ` * - ``std::pair, StringArray> factorize() const`` - std::pair, StringArray> - pd_string_array.h:662 - :ref:`View ` * - ``bool has_na() const`` - bool - pd_string_array.h:424 - :ref:`View ` * - ``size_t nbytes() const`` - size_t - pd_string_array.h:164 - :ref:`View ` * - ``constexpr int ndim() const`` - constexpr int - pd_string_array.h:171 - :ref:`View ` * - ``std::string repr() const`` - std::string - pd_string_array.h:1155 - :ref:`View ` * - ``std::vector shape() const`` - std::vector - pd_string_array.h:178 - :ref:`View ` * - ``size_t size() const`` - size_t - pd_string_array.h:157 - :ref:`View ` * - ``StringArray str_cat(const StringArray& other, const std::string& sep = "") const`` - StringArray - pd_string_array.h:1010 - :ref:`View ` * - ``StringArray str_cat(const std::string& suffix, const std::string& sep = "") const`` - StringArray - pd_string_array.h:1036 - :ref:`View ` * - ``BooleanArray str_contains(const std::string& pat) const`` - BooleanArray - pd_string_array.h:942 - :ref:`View ` * - ``BooleanArray str_endswith(const std::string& suffix) const`` - BooleanArray - pd_string_array.h:986 - :ref:`View ` * - ``IntegerArray str_len() const`` - IntegerArray - pd_string_array.h:780 - :ref:`View ` * - ``StringArray str_lower() const`` - StringArray - pd_string_array.h:798 - :ref:`View ` * - ``StringArray str_lstrip() const`` - StringArray - pd_string_array.h:865 - :ref:`View ` * - ``StringArray str_replace(const std::string& old_str, const std::string& new_str, int count = -1) const`` - StringArray - pd_string_array.h:910 - :ref:`View ` * - ``StringArray str_rstrip() const`` - StringArray - pd_string_array.h:886 - :ref:`View ` * - ``BooleanArray str_startswith(const std::string& prefix) const`` - BooleanArray - pd_string_array.h:963 - :ref:`View ` * - ``StringArray str_strip() const`` - StringArray - pd_string_array.h:840 - :ref:`View ` * - ``StringArray str_upper() const`` - StringArray - pd_string_array.h:819 - :ref:`View ` * - ``void validate_arrays()`` - void - pd_string_array.h:1168 - Internal Methods ---------------- *1 internal methods (prefixed with underscore)* Code Examples ------------- The following examples are extracted from the test suite. .. _example-stringarray-at-0: .. dropdown:: at (pd_test_1_all.cpp:6581) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 6571 :emphasize-lines: 11 // Test isna/notna with float data { std::map> float_data; float_data["X"] = {1.0, std::nan(""), 3.0}; float_data["Y"] = {4.0, 5.0, std::nan("")}; pandas::DataFrame df_na(float_data); auto na_mask = df_na.isna(); // Row 1, col 0 (X) should be NA if (!na_mask.getElementAt({1, 0})) { std::cout << " [FAIL] : in pd_test_dataframe_manipulation() : isna at (1,0) should be true" << std::endl; throw std::runtime_error("pd_test_dataframe_manipulation failed: isna at (1,0)"); } // Row 2, col 1 (Y) should be NA if (!na_mask.getElementAt({2, 1})) { std::cout << " [FAIL] : in pd_test_dataframe_manipulation() : isna at (2,1) should be true" << std::endl; throw std::runtime_error("pd_test_dataframe_manipulation failed: isna at (2,1)"); } // Row 0, col 0 should NOT be NA if (na_mask.getElementAt({0, 0})) { std::cout << " [FAIL] : in pd_test_dataframe_manipulation() : isna at (0,0) should be false" << std::endl; .. _example-stringarray-mask-1: .. dropdown:: mask (pd_test_1_all.cpp:9119) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 9109 :emphasize-lines: 11 void pd_test_datetime_mixin_array_constructor() { std::cout << "========= DatetimeTDMixin array constructor ========================="; // Create DatetimeArray with some values numpy::NDArray data(std::vector{3}); data.setElementAt({0}, numpy::datetime64(1000000000000000000LL, numpy::DateTimeUnit::Nanosecond)); // ~2001 data.setElementAt({1}, numpy::datetime64(1500000000000000000LL, numpy::DateTimeUnit::Nanosecond)); // ~2017 data.setElementAt({2}, numpy::datetime64(1600000000000000000LL, numpy::DateTimeUnit::Nanosecond)); // ~2020 numpy::NDArray mask(std::vector{3}); mask.setElementAt({0}, numpy::bool_(false)); mask.setElementAt({1}, numpy::bool_(false)); mask.setElementAt({2}, numpy::bool_(false)); pandas::DatetimeArray arr(data, mask); pandas::DatetimeTDMixin idx(arr, "timestamps"); bool passed = (idx.size() == 3 && !idx.empty() && idx.name().has_value() && *idx.name() == "timestamps" && idx.inferred_type() == "datetime"); .. _example-stringarray-take-2: .. dropdown:: take (pd_test_1_all.cpp:5903) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 5893 :emphasize-lines: 11 // Inherited Operations Tests // ============================================================================ void pd_test_categorical_index_take() { std::cout << "========= inherited take =============================="; pandas::CategoricalArray arr({"a", "b", "c", "d"}); pandas::CategoricalIndex idx(arr); std::vector indices = {0, 2, 3}; pandas::ExtensionIndex taken = idx.take(indices); bool passed = (taken.size() == 3); if (!passed) { std::cout << " [FAIL] : in pd_test_categorical_index_take()" << std::endl; throw std::runtime_error("pd_test_categorical_index_take failed"); } std::cout << " -> tests passed" << std::endl; } .. _example-stringarray-dropna-3: .. 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-stringarray-fillna-4: .. dropdown:: fillna (pd_test_1_all.cpp:537) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 527 :emphasize-lines: 11 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"); } std::cout << " -> tests passed" << std::endl; } void pd_test_categorical_array_add_categories() { .. _example-stringarray-isna-5: .. dropdown:: isna (pd_test_1_all.cpp:524) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 514 :emphasize-lines: 11 throw std::runtime_error("pd_test_categorical_array_na_handling failed: has_na() should be true"); } // Test count (non-NA) if (arr.count() != 2) { std::cout << " [FAIL] : in pd_test_categorical_array_na_handling() : count() != 2" << std::endl; throw std::runtime_error("pd_test_categorical_array_na_handling failed: count() != 2"); } // 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"); .. _example-stringarray-notna-6: .. dropdown:: notna (pd_test_1_all.cpp:6595) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 6585 :emphasize-lines: 11 if (!na_mask.getElementAt({2, 1})) { std::cout << " [FAIL] : in pd_test_dataframe_manipulation() : isna at (2,1) should be true" << std::endl; throw std::runtime_error("pd_test_dataframe_manipulation failed: isna at (2,1)"); } // Row 0, col 0 should NOT be NA if (na_mask.getElementAt({0, 0})) { std::cout << " [FAIL] : in pd_test_dataframe_manipulation() : isna at (0,0) should be false" << std::endl; throw std::runtime_error("pd_test_dataframe_manipulation failed: isna at (0,0)"); } auto notna_mask = df_na.notna(); if (notna_mask.getElementAt({1, 0})) { std::cout << " [FAIL] : in pd_test_dataframe_manipulation() : notna at (1,0) should be false" << std::endl; throw std::runtime_error("pd_test_dataframe_manipulation failed: notna at (1,0)"); } } // Test fillna { std::map> float_data; float_data["X"] = {1.0, std::nan(""), 3.0}; .. _example-stringarray-count-7: .. dropdown:: count (pd_test_1_all.cpp:66) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 56 :emphasize-lines: 11 if (arr.is_na(0)) { std::cout << " [FAIL] : in pd_test_boolean_array_na_handling() : is_na(0) should be false" << std::endl; throw std::runtime_error("pd_test_boolean_array_na_handling failed: is_na(0) should be false"); } if (!arr.has_na()) { std::cout << " [FAIL] : in pd_test_boolean_array_na_handling() : has_na() should be true" << std::endl; throw std::runtime_error("pd_test_boolean_array_na_handling failed: has_na() should be true"); } if (arr.count() != 2) { std::cout << " [FAIL] : in pd_test_boolean_array_na_handling() : count() should be 2" << std::endl; throw std::runtime_error("pd_test_boolean_array_na_handling failed: count() should be 2"); } std::cout << " -> tests passed" << std::endl; } void pd_test_boolean_array_kleene_and() { std::cout << "========= BooleanArray: Kleene AND ======================= "; .. _example-stringarray-len-8: .. dropdown:: len (pd_test_3_all.cpp:20867) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 20857 :emphasize-lines: 11 auto title_result = s.str().title(); if (title_result[0] != "Hello World" || title_result[1] != "Hello World" || title_result[2] != "Hello World") { std::cout << " [FAIL] : title() failed" << std::endl; throw std::runtime_error("pd_test_str_capitalize_title: title() failed"); } std::cout << " -> tests passed" << std::endl; } // ============================================================================ // Test str().len() // ============================================================================ void pd_test_str_len() { std::cout << "========= Series.str().len() ============================"; pandas::Series s({"a", "bb", "ccc", ""}); auto lens = s.str().len(); if (lens[0] != 1 || lens[1] != 2 || lens[2] != 3 || lens[3] != 0) { std::cout << " [FAIL] : len() failed" << std::endl; .. _example-stringarray-argsort-9: .. dropdown:: argsort (pd_test_1_all.cpp:1304) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1294 :emphasize-lines: 11 std::cout << "========= DatetimeArray: sorting ======================= "; pandas::DatetimeArray arr(std::vector{ "2023-06-15", "NaT", "2023-01-01", "2023-12-31" }); // argsort ascending auto indices = arr.argsort(true, "last"); // Expected order: 2023-01-01(2), 2023-06-15(0), 2023-12-31(3), NaT(1) if (indices.getElementAt({0}) != 2) { std::cout << " [FAIL] : argsort: first should be index 2 (2023-01-01)" << std::endl; throw std::runtime_error("pd_test_datetime_array_sorting failed: argsort first"); } if (indices.getElementAt({3}) != 1) { std::cout << " [FAIL] : argsort: last should be index 1 (NaT)" << std::endl; throw std::runtime_error("pd_test_datetime_array_sorting failed: NaT position"); } .. _example-stringarray-concat-10: .. dropdown:: concat (pd_test_1_all.cpp:17717) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 17707 :emphasize-lines: 11 } void pd_test_period_index_concat() { std::cout << "========= concat factory =============================="; std::vector ordinals1 = {0, 1}; std::vector ordinals2 = {2, 3}; pandas::PeriodIndex idx1(ordinals1, "D"); pandas::PeriodIndex idx2(ordinals2, "D"); pandas::PeriodIndex concatenated = pandas::PeriodIndex::concat({idx1, idx2}); bool passed = (concatenated.size() == 4); if (!passed) { std::cout << " [FAIL] : in pd_test_period_index_concat()" << std::endl; throw std::runtime_error("pd_test_period_index_concat failed"); } std::cout << " -> tests passed" << std::endl; } .. _example-stringarray-to_numpy-11: .. dropdown:: to_numpy (pd_test_1_all.cpp:16764) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 16754 :emphasize-lines: 11 // ===================================================================== // to_numpy Tests // ===================================================================== void pd_test_ndframe_to_numpy() { std::cout << "========= to_numpy =============================================" << std::endl; pandas::Series s({10, 20, 30}); auto arr = s.to_numpy(); bool passed = arr.getSize() == 3; if (!passed) { std::cout << " [FAIL] : in pd_test_ndframe_to_numpy() : size" << std::endl; throw std::runtime_error("pd_test_ndframe_to_numpy failed: size"); } passed = arr.getElementAt({0}) == 10 && arr.getElementAt({1}) == 20 && arr.getElementAt({2}) == 30; if (!passed) { std::cout << " [FAIL] : in pd_test_ndframe_to_numpy() : values" << std::endl; .. _example-stringarray-to_string-12: .. dropdown:: to_string (pd_test_1_all.cpp:2693) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 2683 :emphasize-lines: 11 pandas::PeriodArray arr_m(std::vector{ "2020-01", "NaT", "2025-06" }, "M"); // Year auto years = arr_m.year(); auto y0 = years[0]; if (!y0.has_value() || y0.value() != 2020) { std::cout << " [FAIL] : year[0] should be 2020, got " << (y0.has_value() ? std::to_string(y0.value()) : "NA") << std::endl; throw std::runtime_error("pd_test_period_array_year_month_quarter failed: year[0]"); } auto y1 = years[1]; if (y1.has_value()) { std::cout << " [FAIL] : year[1] should be NA (NaT)" << std::endl; throw std::runtime_error("pd_test_period_array_year_month_quarter failed: year[1] should be NA"); } auto y2 = years[2]; .. _example-stringarray-copy-13: .. dropdown:: copy (pd_test_1_all.cpp:5798) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 5788 :emphasize-lines: 11 // ============================================================================ // Copy/Rename Tests // ============================================================================ void pd_test_categorical_index_copy() { std::cout << "========= copy ========================================"; pandas::CategoricalArray arr({"a", "b", "c"}); pandas::CategoricalIndex idx(arr, "original"); pandas::CategoricalIndex copied = idx.copy(); bool passed = (copied.size() == idx.size() && copied.name() == idx.name() && copied.categories() == idx.categories() && copied.ordered() == idx.ordered()); if (!passed) { std::cout << " [FAIL] : in pd_test_categorical_index_copy()" << std::endl; throw std::runtime_error("pd_test_categorical_index_copy failed"); } std::cout << " -> tests passed" << std::endl; } .. _example-stringarray-unique-14: .. dropdown:: unique (pd_test_1_all.cpp:1345) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1335 :emphasize-lines: 11 pandas::DatetimeArray arr(std::vector{ "2023-01-01", "2023-06-15", "2023-01-01", "NaT", "2023-06-15", "NaT" }); // unique auto uniq = arr.unique(); // Should have: NaT, 2023-01-01, 2023-06-15 (3 unique values) if (uniq.size() != 3) { std::cout << " [FAIL] : unique size should be 3, got " << uniq.size() << std::endl; throw std::runtime_error("pd_test_datetime_array_unique failed: size"); } // factorize auto [codes, uniques] = arr.factorize(); // Codes for NaT should be -1 if (codes.getElementAt({3}) != -1) { .. _example-stringarray-is_na-15: .. dropdown:: is_na (pd_test_1_all.cpp:51) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 41 :emphasize-lines: 11 void pd_test_boolean_array_na_handling() { std::cout << "========= BooleanArray: NA handling ======================= "; pandas::BooleanArray arr({ std::optional(true), std::nullopt, // NA at index 1 std::optional(false) }); if (!arr.is_na(1)) { std::cout << " [FAIL] : in pd_test_boolean_array_na_handling() : is_na(1) should be true" << std::endl; throw std::runtime_error("pd_test_boolean_array_na_handling failed: is_na(1) should be true"); } if (arr.is_na(0)) { std::cout << " [FAIL] : in pd_test_boolean_array_na_handling() : is_na(0) should be false" << std::endl; throw std::runtime_error("pd_test_boolean_array_na_handling failed: is_na(0) should be false"); } if (!arr.has_na()) { .. _example-stringarray-all-16: .. dropdown:: all (pd_test_1_all.cpp:247) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 237 :emphasize-lines: 11 pandas::BooleanArray has_true({ std::optional(false), std::optional(true) }); any_result = has_true.any(); if (!any_result.has_value() || !any_result.value()) { std::cout << " [FAIL] : in pd_test_boolean_array_reductions() : any() with True" << std::endl; throw std::runtime_error("pd_test_boolean_array_reductions failed: any() with True"); } // Test all() pandas::BooleanArray all_true({ std::optional(true), std::optional(true) }); auto all_result = all_true.all(); if (!all_result.has_value() || !all_result.value()) { std::cout << " [FAIL] : in pd_test_boolean_array_reductions() : all() of all True" << std::endl; throw std::runtime_error("pd_test_boolean_array_reductions failed: all() all True"); } .. _example-stringarray-any-17: .. dropdown:: any (pd_test_1_all.cpp:226) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 216 :emphasize-lines: 11 std::cout << " [FAIL] : in pd_test_boolean_array_kleene_not() : ~NA should be NA" << std::endl; throw std::runtime_error("pd_test_boolean_array_kleene_not failed: ~NA"); } std::cout << " -> tests passed" << std::endl; } void pd_test_boolean_array_reductions() { std::cout << "========= BooleanArray: reductions ======================= "; // Test any() pandas::BooleanArray all_false({ std::optional(false), std::optional(false) }); auto any_result = all_false.any(); if (!any_result.has_value() || any_result.value()) { std::cout << " [FAIL] : in pd_test_boolean_array_reductions() : any() of all False" << std::endl; throw std::runtime_error("pd_test_boolean_array_reductions failed: any() all False"); } .. _example-stringarray-argmax-18: .. dropdown:: argmax (pd_test_1_all.cpp:1323) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1313 :emphasize-lines: 11 } // argmin auto min_idx = arr.argmin(); if (!min_idx.has_value() || min_idx.value() != 2) { std::cout << " [FAIL] : argmin should be 2 (2023-01-01)" << std::endl; throw std::runtime_error("pd_test_datetime_array_sorting failed: argmin"); } // argmax auto max_idx = arr.argmax(); if (!max_idx.has_value() || max_idx.value() != 3) { std::cout << " [FAIL] : argmax should be 3 (2023-12-31)" << std::endl; throw std::runtime_error("pd_test_datetime_array_sorting failed: argmax"); } std::cout << " -> tests passed" << std::endl; } void pd_test_datetime_array_unique() { std::cout << "========= DatetimeArray: unique/factorize ======================= "; .. _example-stringarray-argmin-19: .. dropdown:: argmin (pd_test_1_all.cpp:1316) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1306 :emphasize-lines: 11 if (indices.getElementAt({0}) != 2) { std::cout << " [FAIL] : argsort: first should be index 2 (2023-01-01)" << std::endl; throw std::runtime_error("pd_test_datetime_array_sorting failed: argsort first"); } if (indices.getElementAt({3}) != 1) { std::cout << " [FAIL] : argsort: last should be index 1 (NaT)" << std::endl; throw std::runtime_error("pd_test_datetime_array_sorting failed: NaT position"); } // argmin auto min_idx = arr.argmin(); if (!min_idx.has_value() || min_idx.value() != 2) { std::cout << " [FAIL] : argmin should be 2 (2023-01-01)" << std::endl; throw std::runtime_error("pd_test_datetime_array_sorting failed: argmin"); } // argmax auto max_idx = arr.argmax(); if (!max_idx.has_value() || max_idx.value() != 3) { std::cout << " [FAIL] : argmax should be 3 (2023-12-31)" << std::endl; throw std::runtime_error("pd_test_datetime_array_sorting failed: argmax"); .. _example-stringarray-data-20: .. dropdown:: data (pd_test_1_all.cpp:9114) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 9104 :emphasize-lines: 11 throw std::runtime_error("pd_test_datetime_mixin_default_constructor failed"); } std::cout << " -> tests passed" << std::endl; } void pd_test_datetime_mixin_array_constructor() { std::cout << "========= DatetimeTDMixin array constructor ========================="; // Create DatetimeArray with some values numpy::NDArray data(std::vector{3}); data.setElementAt({0}, numpy::datetime64(1000000000000000000LL, numpy::DateTimeUnit::Nanosecond)); // ~2001 data.setElementAt({1}, numpy::datetime64(1500000000000000000LL, numpy::DateTimeUnit::Nanosecond)); // ~2017 data.setElementAt({2}, numpy::datetime64(1600000000000000000LL, numpy::DateTimeUnit::Nanosecond)); // ~2020 numpy::NDArray mask(std::vector{3}); mask.setElementAt({0}, numpy::bool_(false)); mask.setElementAt({1}, numpy::bool_(false)); mask.setElementAt({2}, numpy::bool_(false)); pandas::DatetimeArray arr(data, mask); .. _example-stringarray-dtype-21: .. dropdown:: dtype (pd_test_1_all.cpp:295) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 285 :emphasize-lines: 11 throw std::runtime_error("pd_test_boolean_array_reductions failed: mean"); } std::cout << " -> tests passed" << std::endl; } void pd_test_boolean_array_dtype() { std::cout << "========= BooleanArray: dtype ======================= "; pandas::BooleanArray arr; if (arr.dtype().name() != "boolean") { std::cout << " [FAIL] : in pd_test_boolean_array_dtype() : dtype name should be 'boolean'" << std::endl; throw std::runtime_error("pd_test_boolean_array_dtype failed: dtype name"); } if (arr.dtype().kind() != "b") { std::cout << " [FAIL] : in pd_test_boolean_array_dtype() : dtype kind should be 'b'" << std::endl; throw std::runtime_error("pd_test_boolean_array_dtype failed: dtype kind"); } std::cout << " -> tests passed" << std::endl; .. _example-stringarray-empty-22: .. dropdown:: empty (pd_test_1_all.cpp:941) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 931 :emphasize-lines: 11 #include "../pandas/pd_config.h" namespace dataframe_tests { namespace dataframe_tests_config { void pd_test_config_version() { std::cout << "========= df_config: version info ======================= "; const char* version = pandas::DataFrameInfo::version(); if (version == nullptr || std::string(version).empty()) { std::cout << "[FAIL] : in pd_test_config_version() : version is null or empty" << std::endl; throw std::runtime_error("pd_test_config_version failed: version is null or empty"); } std::cout << "-> tests passed" << std::endl; } void pd_test_config_na_repr() { std::cout << "========= df_config: NA representation ======================= "; const char* na_repr = pandas::DataFrameConfig::get_na_repr(); if (na_repr == nullptr) { .. _example-stringarray-factorize-23: .. dropdown:: factorize (pd_test_1_all.cpp:1353) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1343 :emphasize-lines: 11 // unique auto uniq = arr.unique(); // Should have: NaT, 2023-01-01, 2023-06-15 (3 unique values) if (uniq.size() != 3) { std::cout << " [FAIL] : unique size should be 3, got " << uniq.size() << std::endl; throw std::runtime_error("pd_test_datetime_array_unique failed: size"); } // factorize auto [codes, uniques] = arr.factorize(); // Codes for NaT should be -1 if (codes.getElementAt({3}) != -1) { std::cout << " [FAIL] : factorize: NaT code should be -1" << std::endl; throw std::runtime_error("pd_test_datetime_array_unique failed: NaT code"); } // Same values should have same codes if (codes.getElementAt({0}) != codes.getElementAt({2})) { std::cout << " [FAIL] : factorize: 2023-01-01 values should have same code" << std::endl; throw std::runtime_error("pd_test_datetime_array_unique failed: same code"); } .. _example-stringarray-has_na-24: .. dropdown:: has_na (pd_test_1_all.cpp:61) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 51 :emphasize-lines: 11 if (!arr.is_na(1)) { std::cout << " [FAIL] : in pd_test_boolean_array_na_handling() : is_na(1) should be true" << std::endl; throw std::runtime_error("pd_test_boolean_array_na_handling failed: is_na(1) should be true"); } if (arr.is_na(0)) { std::cout << " [FAIL] : in pd_test_boolean_array_na_handling() : is_na(0) should be false" << std::endl; throw std::runtime_error("pd_test_boolean_array_na_handling failed: is_na(0) should be false"); } if (!arr.has_na()) { std::cout << " [FAIL] : in pd_test_boolean_array_na_handling() : has_na() should be true" << std::endl; throw std::runtime_error("pd_test_boolean_array_na_handling failed: has_na() should be true"); } if (arr.count() != 2) { std::cout << " [FAIL] : in pd_test_boolean_array_na_handling() : count() should be 2" << std::endl; throw std::runtime_error("pd_test_boolean_array_na_handling failed: count() should be 2"); } std::cout << " -> tests passed" << std::endl; .. _example-stringarray-nbytes-25: .. dropdown:: nbytes (pd_test_1_all.cpp:6214) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 6204 :emphasize-lines: 11 } // Test empty DataFrame pandas::DataFrame empty_df; if (!empty_df.empty()) { std::cout << " [FAIL] : in pd_test_dataframe_properties() : should be empty" << std::endl; throw std::runtime_error("pd_test_dataframe_properties failed: should be empty"); } // Test nbytes > 0 for non-empty if (df.nbytes() == 0) { std::cout << " [FAIL] : in pd_test_dataframe_properties() : nbytes should be > 0" << std::endl; throw std::runtime_error("pd_test_dataframe_properties failed: nbytes should be > 0"); } // Test columns index if (df.columns().size() != 3) { std::cout << " [FAIL] : in pd_test_dataframe_properties() : columns size != 3" << std::endl; throw std::runtime_error("pd_test_dataframe_properties failed: columns size != 3"); } .. _example-stringarray-ndim-26: .. dropdown:: ndim (pd_test_1_all.cpp:6195) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 6185 :emphasize-lines: 11 pandas::DataFrame df(data); // Test shape auto shape = df.shape(); if (shape.size() != 2 || shape[0] != 4 || shape[1] != 3) { std::cout << " [FAIL] : in pd_test_dataframe_properties() : shape mismatch" << std::endl; throw std::runtime_error("pd_test_dataframe_properties failed: shape mismatch"); } // Test ndim if (df.ndim() != 2) { std::cout << " [FAIL] : in pd_test_dataframe_properties() : ndim != 2" << std::endl; throw std::runtime_error("pd_test_dataframe_properties failed: ndim != 2"); } // Test empty if (df.empty()) { std::cout << " [FAIL] : in pd_test_dataframe_properties() : should not be empty" << std::endl; throw std::runtime_error("pd_test_dataframe_properties failed: should not be empty"); } .. _example-stringarray-repr-27: .. dropdown:: repr (pd_test_1_all.cpp:10906) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 10896 :emphasize-lines: 11 std::cout << " -> tests passed" << std::endl; } void pd_test_extension_index_repr() { std::cout << "========= repr ========================="; pandas::CategoricalArray arr({"a", "b", "c"}); // Use ExtensionIndex directly to test base class repr pandas::ExtensionIndex idx(arr, "test"); std::string repr_str = idx.repr(); bool passed = (!repr_str.empty() && repr_str.find("ExtensionIndex") != std::string::npos); if (!passed) { std::cout << " [FAIL] : in pd_test_extension_index_repr() : repr check failed" << std::endl; throw std::runtime_error("pd_test_extension_index_repr failed"); } std::cout << " -> tests passed" << std::endl; } .. _example-stringarray-shape-28: .. dropdown:: shape (pd_test_1_all.cpp:6188) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 6178 :emphasize-lines: 11 std::cout << "========= properties ======================="; std::map> data; data["A"] = {1.0, 2.0, 3.0, 4.0}; data["B"] = {5.0, 6.0, 7.0, 8.0}; data["C"] = {9.0, 10.0, 11.0, 12.0}; pandas::DataFrame df(data); // Test shape auto shape = df.shape(); if (shape.size() != 2 || shape[0] != 4 || shape[1] != 3) { std::cout << " [FAIL] : in pd_test_dataframe_properties() : shape mismatch" << std::endl; throw std::runtime_error("pd_test_dataframe_properties failed: shape mismatch"); } // Test ndim if (df.ndim() != 2) { std::cout << " [FAIL] : in pd_test_dataframe_properties() : ndim != 2" << std::endl; throw std::runtime_error("pd_test_dataframe_properties failed: ndim != 2"); } .. _example-stringarray-size-29: .. dropdown:: size (pd_test_1_all.cpp:22) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 12 :emphasize-lines: 11 #include "../pandas/pd_boolean_array.h" namespace dataframe_tests { namespace dataframe_tests_boolean_array { void pd_test_boolean_array_constructors() { std::cout << "========= BooleanArray: constructors ======================= "; // Default constructor pandas::BooleanArray arr1; if (arr1.size() != 0) { std::cout << " [FAIL] : in pd_test_boolean_array_constructors() : default constructor size != 0" << std::endl; throw std::runtime_error("pd_test_boolean_array_constructors failed: default constructor size != 0"); } // Initializer list constructor pandas::BooleanArray arr2({ std::optional(true), std::optional(false), std::nullopt, std::optional(true) .. _example-stringarray-str_cat-30: .. dropdown:: str_cat (pd_test_1_all.cpp:3822) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 3812 :emphasize-lines: 11 std::nullopt, std::optional("foo") }); pandas::StringArray arr2({ std::optional("world"), std::optional("test"), std::nullopt }); // Array concatenation auto result = arr1.str_cat(arr2, " "); if (result[0].value() != "hello world") { std::cout << " [FAIL] : str_cat: expected 'hello world'" << std::endl; throw std::runtime_error("pd_test_string_array_str_cat failed: array cat"); } if (result[1].has_value()) { std::cout << " [FAIL] : str_cat: NA + value should be NA" << std::endl; throw std::runtime_error("pd_test_string_array_str_cat failed: NA + value"); } if (result[2].has_value()) { std::cout << " [FAIL] : str_cat: value + NA should be NA" << std::endl; .. _example-stringarray-str_cat-31: .. dropdown:: str_cat (pd_test_1_all.cpp:3822) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 3812 :emphasize-lines: 11 std::nullopt, std::optional("foo") }); pandas::StringArray arr2({ std::optional("world"), std::optional("test"), std::nullopt }); // Array concatenation auto result = arr1.str_cat(arr2, " "); if (result[0].value() != "hello world") { std::cout << " [FAIL] : str_cat: expected 'hello world'" << std::endl; throw std::runtime_error("pd_test_string_array_str_cat failed: array cat"); } if (result[1].has_value()) { std::cout << " [FAIL] : str_cat: NA + value should be NA" << std::endl; throw std::runtime_error("pd_test_string_array_str_cat failed: NA + value"); } if (result[2].has_value()) { std::cout << " [FAIL] : str_cat: value + NA should be NA" << std::endl; .. _example-stringarray-str_contains-32: .. dropdown:: str_contains (pd_test_1_all.cpp:3768) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 3758 :emphasize-lines: 11 std::cout << "========= StringArray: string predicates ======================= "; pandas::StringArray arr({ std::optional("hello world"), std::nullopt, std::optional("python"), std::optional("hello") }); // str_contains auto contains = arr.str_contains("llo"); if (!contains[0].has_value() || !contains[0].value()) { std::cout << " [FAIL] : str_contains: 'hello world' contains 'llo'" << std::endl; throw std::runtime_error("pd_test_string_array_str_predicates failed: contains"); } if (contains[1].has_value()) { std::cout << " [FAIL] : str_contains: NA should propagate" << std::endl; throw std::runtime_error("pd_test_string_array_str_predicates failed: contains NA"); } if (!contains[2].has_value() || contains[2].value()) { std::cout << " [FAIL] : str_contains: 'python' does not contain 'llo'" << std::endl; .. _example-stringarray-str_endswith-33: .. dropdown:: str_endswith (pd_test_1_all.cpp:3794) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 3784 :emphasize-lines: 11 if (!starts[0].has_value() || !starts[0].value()) { std::cout << " [FAIL] : str_startswith: 'hello world' starts with 'hello'" << std::endl; throw std::runtime_error("pd_test_string_array_str_predicates failed: startswith"); } if (!starts[2].has_value() || starts[2].value()) { std::cout << " [FAIL] : str_startswith: 'python' does not start with 'hello'" << std::endl; throw std::runtime_error("pd_test_string_array_str_predicates failed: startswith python"); } // str_endswith auto ends = arr.str_endswith("ld"); if (!ends[0].has_value() || !ends[0].value()) { std::cout << " [FAIL] : str_endswith: 'hello world' ends with 'ld'" << std::endl; throw std::runtime_error("pd_test_string_array_str_predicates failed: endswith"); } if (!ends[2].has_value() || ends[2].value()) { std::cout << " [FAIL] : str_endswith: 'python' does not end with 'ld'" << std::endl; throw std::runtime_error("pd_test_string_array_str_predicates failed: endswith python"); } std::cout << " -> tests passed" << std::endl; .. _example-stringarray-str_len-34: .. dropdown:: str_len (pd_test_1_all.cpp:3728) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 3718 :emphasize-lines: 11 void pd_test_string_array_str_len() { std::cout << "========= StringArray: str_len ======================= "; pandas::StringArray arr({ std::optional("abc"), std::nullopt, std::optional("hello"), std::optional("") }); auto lengths = arr.str_len(); auto len0 = lengths[0]; if (!len0.has_value() || len0.value() != 3) { std::cout << " [FAIL] : str_len[0] should be 3" << std::endl; throw std::runtime_error("pd_test_string_array_str_len failed: len[0]"); } auto len1 = lengths[1]; if (len1.has_value()) { std::cout << " [FAIL] : str_len[1] should be NA" << std::endl; .. _example-stringarray-str_lower-35: .. dropdown:: str_lower (pd_test_1_all.cpp:3681) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 3671 :emphasize-lines: 11 if (upper[0].value() != "HELLO WORLD") { std::cout << " [FAIL] : str_upper: expected 'HELLO WORLD'" << std::endl; throw std::runtime_error("pd_test_string_array_str_methods failed: str_upper"); } if (upper[1].has_value()) { std::cout << " [FAIL] : str_upper: NA should propagate" << std::endl; throw std::runtime_error("pd_test_string_array_str_methods failed: str_upper NA"); } // str_lower auto lower = arr.str_lower(); if (lower[0].value() != "hello world") { std::cout << " [FAIL] : str_lower: expected 'hello world'" << std::endl; throw std::runtime_error("pd_test_string_array_str_methods failed: str_lower"); } // str_strip auto stripped = arr.str_strip(); if (stripped[2].value() != "spaced") { std::cout << " [FAIL] : str_strip: expected 'spaced'" << std::endl; throw std::runtime_error("pd_test_string_array_str_methods failed: str_strip"); .. _example-stringarray-str_lstrip-36: .. dropdown:: str_lstrip (pd_test_1_all.cpp:3695) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 3685 :emphasize-lines: 11 } // str_strip auto stripped = arr.str_strip(); if (stripped[2].value() != "spaced") { std::cout << " [FAIL] : str_strip: expected 'spaced'" << std::endl; throw std::runtime_error("pd_test_string_array_str_methods failed: str_strip"); } // str_lstrip auto lstripped = arr.str_lstrip(); if (lstripped[2].value() != "spaced ") { std::cout << " [FAIL] : str_lstrip: expected 'spaced '" << std::endl; throw std::runtime_error("pd_test_string_array_str_methods failed: str_lstrip"); } // str_rstrip auto rstripped = arr.str_rstrip(); if (rstripped[2].value() != " spaced") { std::cout << " [FAIL] : str_rstrip: expected ' spaced'" << std::endl; throw std::runtime_error("pd_test_string_array_str_methods failed: str_rstrip"); .. _example-stringarray-str_replace-37: .. dropdown:: str_replace (pd_test_1_all.cpp:3709) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 3699 :emphasize-lines: 11 } // str_rstrip auto rstripped = arr.str_rstrip(); if (rstripped[2].value() != " spaced") { std::cout << " [FAIL] : str_rstrip: expected ' spaced'" << std::endl; throw std::runtime_error("pd_test_string_array_str_methods failed: str_rstrip"); } // str_replace auto replaced = arr.str_replace("World", "Universe"); if (replaced[0].value() != "Hello Universe") { std::cout << " [FAIL] : str_replace: expected 'Hello Universe'" << std::endl; throw std::runtime_error("pd_test_string_array_str_methods failed: str_replace"); } std::cout << " -> tests passed" << std::endl; } void pd_test_string_array_str_len() { std::cout << "========= StringArray: str_len ======================= "; .. _example-stringarray-str_rstrip-38: .. dropdown:: str_rstrip (pd_test_1_all.cpp:3702) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 3692 :emphasize-lines: 11 } // str_lstrip auto lstripped = arr.str_lstrip(); if (lstripped[2].value() != "spaced ") { std::cout << " [FAIL] : str_lstrip: expected 'spaced '" << std::endl; throw std::runtime_error("pd_test_string_array_str_methods failed: str_lstrip"); } // str_rstrip auto rstripped = arr.str_rstrip(); if (rstripped[2].value() != " spaced") { std::cout << " [FAIL] : str_rstrip: expected ' spaced'" << std::endl; throw std::runtime_error("pd_test_string_array_str_methods failed: str_rstrip"); } // str_replace auto replaced = arr.str_replace("World", "Universe"); if (replaced[0].value() != "Hello Universe") { std::cout << " [FAIL] : str_replace: expected 'Hello Universe'" << std::endl; throw std::runtime_error("pd_test_string_array_str_methods failed: str_replace"); .. _example-stringarray-str_startswith-39: .. dropdown:: str_startswith (pd_test_1_all.cpp:3783) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 3773 :emphasize-lines: 11 if (contains[1].has_value()) { std::cout << " [FAIL] : str_contains: NA should propagate" << std::endl; throw std::runtime_error("pd_test_string_array_str_predicates failed: contains NA"); } if (!contains[2].has_value() || contains[2].value()) { std::cout << " [FAIL] : str_contains: 'python' does not contain 'llo'" << std::endl; throw std::runtime_error("pd_test_string_array_str_predicates failed: contains python"); } // str_startswith auto starts = arr.str_startswith("hello"); if (!starts[0].has_value() || !starts[0].value()) { std::cout << " [FAIL] : str_startswith: 'hello world' starts with 'hello'" << std::endl; throw std::runtime_error("pd_test_string_array_str_predicates failed: startswith"); } if (!starts[2].has_value() || starts[2].value()) { std::cout << " [FAIL] : str_startswith: 'python' does not start with 'hello'" << std::endl; throw std::runtime_error("pd_test_string_array_str_predicates failed: startswith python"); } // str_endswith .. _example-stringarray-str_strip-40: .. dropdown:: str_strip (pd_test_1_all.cpp:3688) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 3678 :emphasize-lines: 11 } // str_lower auto lower = arr.str_lower(); if (lower[0].value() != "hello world") { std::cout << " [FAIL] : str_lower: expected 'hello world'" << std::endl; throw std::runtime_error("pd_test_string_array_str_methods failed: str_lower"); } // str_strip auto stripped = arr.str_strip(); if (stripped[2].value() != "spaced") { std::cout << " [FAIL] : str_strip: expected 'spaced'" << std::endl; throw std::runtime_error("pd_test_string_array_str_methods failed: str_strip"); } // str_lstrip auto lstripped = arr.str_lstrip(); if (lstripped[2].value() != "spaced ") { std::cout << " [FAIL] : str_lstrip: expected 'spaced '" << std::endl; throw std::runtime_error("pd_test_string_array_str_methods failed: str_lstrip"); .. _example-stringarray-str_upper-41: .. dropdown:: str_upper (pd_test_1_all.cpp:3670) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 3660 :emphasize-lines: 11 void pd_test_string_array_str_methods() { std::cout << "========= StringArray: string methods ======================= "; pandas::StringArray arr({ std::optional("Hello World"), std::nullopt, std::optional(" spaced ") }); // str_upper auto upper = arr.str_upper(); if (upper[0].value() != "HELLO WORLD") { std::cout << " [FAIL] : str_upper: expected 'HELLO WORLD'" << std::endl; throw std::runtime_error("pd_test_string_array_str_methods failed: str_upper"); } if (upper[1].has_value()) { std::cout << " [FAIL] : str_upper: NA should propagate" << std::endl; throw std::runtime_error("pd_test_string_array_str_methods failed: str_upper NA"); } // str_lower