Skip to content

[Python] Nested ExtensionArray conversion to/from pandas/numpy #33036

Description

@asfimport

user@ thread: https://lists.apache.org/thread/dhnxq0g4kgdysjowftfv3z5ngj780xpb
repro gist: https://gist.github.com/changhiskhan/4163f8cec675a2418a69ec9168d5fdd9

Arrow => numpy/pandas

For a non-nested array, pa.ExtensionArray.to_numpy automatically "lowers" to the storage type (as expected). However this is not done for nested arrays:

importpyarrowaspaclassLabelType(pa.ExtensionType):
def__init__(self):
super(LabelType, self).__init__(pa.string(), "label")
def__arrow_ext_serialize__(self):
returnb""@classmethoddef__arrow_ext_deserialize__(cls, storage_type, serialized):
returnLabelType()
storage=pa.array(["dog", "cat", "horse"])
ext_arr=pa.ExtensionArray.from_storage(LabelType(), storage)
offsets=pa.array([0, 1])
list_arr=pa.ListArray.from_arrays(offsets, ext_arr)
list_arr.to_numpy()
---------------------------------------------------------------------------
ArrowNotImplementedErrorTraceback (mostrecentcalllast)
CellIn [15], line1
----> 1list_arr.to_numpy()
File /mnt/lance/.venv/lance/lib/python3.10/site-packages/pyarrow/array.pxi:1445, inpyarrow.lib.Array.to_numpy()
File /mnt/lance/.venv/lance/lib/python3.10/site-packages/pyarrow/error.pxi:121, inpyarrow.lib.check_status()
ArrowNotImplementedError: NotimplementedtypeforArrowlisttopandas: extension<label<LabelType>>

As mentioned on the user thread linked from the top, a fairly generic solution would just have the conversion default to the storage array's to_numpy.


pandas/numpy => Arrow

Equivalently, conversion to Arrow is also difficult for nested extension types:

if I have say a pandas DataFrame that has a column of list-of-string and I want to convert that to list-of-label Array. Currently I have to:

  1. Convert to list-of-string (storage) numpy array to pa.list_(pa.string())
  2. Convert the string values array to ExtensionArray, then reconstitue a list array using the ExtensionArray combined with the offsets from the result of step 1
importpyarrowaspaimportpandasaspddf=pd.DataFrame({'labels': [["dog", "horse", "cat"], ["person", "person", "car", "car"]]})
list_of_storage=pa.array(df.labels)
ext_values=pa.ExtensionArray.from_storage(LabelType(), list_of_storage.values)
list_of_ext=pa.ListArray.from_arrays(offsets=list_of_storage.offsets, values=ext_values)

For non-nested columns, one can achieve easier conversion by defining a pandas extension dtype, but i don't think that works for a nested column. You would instead have to fallback to something like pa.ExtensionArray.from_storage (or from_pandas?) to do the trick. Even that doesn't necessarily work for something like a dictionary column because you'd have to pass in the dictionary somehow. Off the cuff, one could provide a custom lambda to pa.Table.from_pandas that is used for either specified column names / data types?

Thanks in advance for the consideration!

Reporter: Chang She / @changhiskhan
Assignee: Miles Granger / @milesgranger

Related issues:

PRs and other links:

Note: This issue was originally created as ARROW-17813. Please see the migration documentation for further details.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions