diff --git a/python/pyarrow/src/arrow/python/arrow_to_pandas.cc b/python/pyarrow/src/arrow/python/arrow_to_pandas.cc index eb60d9d54f8..9da449c49fe 100644 --- a/python/pyarrow/src/arrow/python/arrow_to_pandas.cc +++ b/python/pyarrow/src/arrow/python/arrow_to_pandas.cc @@ -193,12 +193,17 @@ static inline bool ListTypeSupported(const DataType& type) { case Type::HALF_FLOAT: case Type::FLOAT: case Type::DOUBLE: + case Type::DECIMAL32: + case Type::DECIMAL64: case Type::DECIMAL128: case Type::DECIMAL256: case Type::BINARY: case Type::LARGE_BINARY: + case Type::BINARY_VIEW: + case Type::FIXED_SIZE_BINARY: case Type::STRING: case Type::LARGE_STRING: + case Type::STRING_VIEW: case Type::DATE32: case Type::DATE64: case Type::STRUCT: @@ -781,7 +786,8 @@ enable_if_list_like ConvertListsLike(PandasOptions options, // flattened_values array different. std::shared_ptr flattened_values = arr.values()->Slice( arr.value_offset(0), arr.value_offset(arr.length()) - arr.value_offset(0)); - if (arr.value_type()->id() == Type::EXTENSION) { + if (arr.value_type()->id() == Type::EXTENSION && + !IsUuidExtension(*arr.value_type())) { const auto& arr_ext = checked_cast(*flattened_values); value_arrays.emplace_back(arr_ext.storage()); } else { @@ -792,7 +798,7 @@ enable_if_list_like ConvertListsLike(PandasOptions options, using ListArrayType = typename ListArrayT::TypeClass; const auto& list_type = checked_cast(*data.type()); auto value_type = list_type.value_type(); - if (value_type->id() == Type::EXTENSION) { + if (value_type->id() == Type::EXTENSION && !IsUuidExtension(*value_type)) { value_type = checked_cast(*value_type).storage_type(); } diff --git a/python/pyarrow/tests/test_extension_type.py b/python/pyarrow/tests/test_extension_type.py index a9d15cfec10..a186fefe8fc 100644 --- a/python/pyarrow/tests/test_extension_type.py +++ b/python/pyarrow/tests/test_extension_type.py @@ -1454,6 +1454,19 @@ def test_uuid_to_pandas(): ) +@pytest.mark.pandas +@pytest.mark.parametrize("list_array_class", [pa.ListArray, pa.LargeListArray]) +def test_list_of_uuid_to_pandas(list_array_class): + # GH-55298 + import pandas as pd + import pandas.testing as tm + values = [uuid4(), None, uuid4()] + array = list_array_class.from_arrays( + [0, 2, 3, 3], pa.array(values, type=pa.uuid())) + expected = pd.Series([values[:2], values[2:], []]) + tm.assert_series_equal(array.to_pandas(), expected) + + @pytest.mark.pandas def test_uuid_to_pandas_options(): values = [uuid4(), uuid4()] * 2 diff --git a/python/pyarrow/tests/test_pandas.py b/python/pyarrow/tests/test_pandas.py index 2391cb26000..90633a20513 100644 --- a/python/pyarrow/tests/test_pandas.py +++ b/python/pyarrow/tests/test_pandas.py @@ -2505,6 +2505,23 @@ def test_large_binary_list(self): s, pd.Series([["aa", "bb"], None, ["cc"], []]), check_names=False) + @pytest.mark.parametrize(("value_type", "values"), [ + (pa.string_view(), ["aa", None, "bb"]), + (pa.binary_view(), [b"aa", None, b"bb"]), + (pa.binary(2), [b"aa", None, b"bb"]), + (pa.decimal32(3, 1), [decimal.Decimal("1.5"), None, decimal.Decimal("-2.0")]), + (pa.decimal64(3, 1), [decimal.Decimal("1.5"), None, decimal.Decimal("-2.0")]), + ]) + def test_list_of_view_decimal_and_fixed_size_binary(self, value_type, values): + # GH-55298 + expected = [values, None, []] + for list_type_factory in (pa.list_, pa.large_list, pa.list_view): + arr = pa.array(expected, type=list_type_factory(value_type)) + tm.assert_series_equal(arr.to_pandas(), pd.Series(expected), + check_names=False) + tm.assert_frame_equal(pa.table({"a": arr}).to_pandas(), + pd.DataFrame({"a": expected})) + def test_list_of_dictionary(self): child = pa.array(["foo", "bar", None, "foo"]).dictionary_encode() arr = pa.ListArray.from_arrays([0, 1, 3, 3, 4], child)