Функциональность PyArrow
pandas может использовать PyArrow, чтобы расширить функциональность и улучшить производительность различных API. Это включает:
Более широкий набор типов данных по сравнению с NumPy
Поддержка пропущенных данных (NA) для всех типов данных
Интеграция высокопроизводительных читателей IO
Упрощение взаимодействия с другими библиотеками фреймворков данных, основанных на спецификации Apache Arrow (например, polars, cuDF)
Для использования этой функциональности, пожалуйста, убедитесь, что вы установили минимально поддерживаемую версию PyArrow.
Интеграция структур данных
Series, Index или столбцы DataFrame могут напрямую опираться на pyarrow.ChunkedArray, который похож на массив NumPy. Для создания этих объектов из основных структур данных pandas можно передать строку типа, за которой следует [pyarrow], например "int64[pyarrow]"" в параметр dtype
In [1]: ser = pd.Series([-1.5, 0.2, None], dtype="float32[pyarrow]")
In [2]: ser
Out[2]:
0 -1.5
1 0.2
2 <NA>
dtype: float[pyarrow]
In [3]: idx = pd.Index([True, None], dtype="bool[pyarrow]")
In [4]: idx
Out[4]: Index([True, <NA>], dtype='bool[pyarrow]')
In [5]: df = pd.DataFrame([[1, 2], [3, 4]], dtype="uint64[pyarrow]")
In [6]: df
Out[6]:
0 1
0 1 2
1 3 4
Примечание
Псевдоним строки "string[pyarrow]" соответствует pd.StringDtype("pyarrow"), который не эквивалентен указанию dtype=pd.ArrowDtype(pa.string()). В целом, операции с данными будут вести себя аналогично, за исключением того, что pd.StringDtype("pyarrow") может возвращать типы NumPy с поддержкой отсутствующих значений, в то время как pd.ArrowDtype(pa.string()) вернёт ArrowDtype.
In [7]: import pyarrow as pa
In [8]: data = list("abc")
In [9]: ser_sd = pd.Series(data, dtype="string[pyarrow]")
In [10]: ser_ad = pd.Series(data, dtype=pd.ArrowDtype(pa.string()))
In [11]: ser_ad.dtype == ser_sd.dtype
Out[11]: False
In [12]: ser_sd.str.contains("a")
Out[12]:
0 True
1 False
2 False
dtype: boolean
In [13]: ser_ad.str.contains("a")
Out[13]:
0 True
1 False
2 False
dtype: bool[pyarrow]
Для типов PyArrow, которые принимают параметры, вы можете передать тип PyArrow с этими параметрами в ArrowDtype, чтобы использовать его в параметре dtype.
In [14]: import pyarrow as pa
In [15]: list_str_type = pa.list_(pa.string())
In [16]: ser = pd.Series([["hello"], ["there"]], dtype=pd.ArrowDtype(list_str_type))
In [17]: ser
Out[17]:
0 ['hello']
1 ['there']
dtype: list<item: string>[pyarrow]
In [18]: from datetime import time
In [19]: idx = pd.Index([time(12, 30), None], dtype=pd.ArrowDtype(pa.time64("us")))
In [20]: idx
Out[20]: Index([12:30:00, <NA>], dtype='time64[us][pyarrow]')
In [21]: from decimal import Decimal
In [22]: decimal_type = pd.ArrowDtype(pa.decimal128(3, scale=2))
In [23]: data = [[Decimal("3.19"), None], [None, Decimal("-1.23")]]
In [24]: df = pd.DataFrame(data, dtype=decimal_type)
In [25]: df
Out[25]:
0 1
0 3.19 <NA>
1 <NA> -1.23
Если у вас уже есть pyarrow.Array или pyarrow.ChunkedArray, вы можете передать его в arrays.ArrowExtensionArray, чтобы создать связанный Series, Index или DataFrame объект.
In [26]: pa_array = pa.array(
....: [{"1": "2"}, {"10": "20"}, None],
....: type=pa.map_(pa.string(), pa.string()),
....: )
....:
In [27]: ser = pd.Series(pd.arrays.ArrowExtensionArray(pa_array))
In [28]: ser
Out[28]:
0 [('1', '2')]
1 [('10', '20')]
2 <NA>
dtype: map<string, string>[pyarrow]
Для получения pyarrow pyarrow.ChunkedArray из Series или Index вы можете вызвать конструктор массива pyarrow для Series или Index.
In [29]: ser = pd.Series([1, 2, None], dtype="uint8[pyarrow]")
In [30]: pa.array(ser)
Out[30]:
<pyarrow.lib.UInt8Array object at 0x7ff2a2968400>
[
1,
2,
null
]
In [31]: idx = pd.Index(ser)
In [32]: pa.array(idx)
Out[32]:
<pyarrow.lib.UInt8Array object at 0x7ff2a2968460>
[
1,
2,
null
]
Для преобразования pyarrow.Table в DataFrame, вы можете вызвать метод pyarrow.Table.to_pandas() с types_mapper=pd.ArrowDtype.
In [33]: table = pa.table([pa.array([1, 2, 3], type=pa.int64())], names=["a"])
In [34]: df = table.to_pandas(types_mapper=pd.ArrowDtype)
In [35]: df
Out[35]:
a
0 1
1 2
2 3
In [36]: df.dtypes
Out[36]:
a int64[pyarrow]
dtype: object
Операции
Интеграция структур данных PyArrow реализована через интерфейс ExtensionArray pandas; поэтому поддерживаемая функциональность существует там, где этот интерфейс интегрирован в API pandas. Кроме того, эта функциональность ускорена с помощью функций вычисления PyArrow в случае их доступности. Это включает:
Числовые агрегации
Числовые арифметические операции
Округление числовых значений
Логические и сравнительные функции
Функциональность строк
Функциональность дат и времени
Ниже приведены лишь некоторые примеры операций, ускоренных нативными функциями вычисления PyArrow.
In [37]: import pyarrow as pa
In [38]: ser = pd.Series([-1.545, 0.211, None], dtype="float32[pyarrow]")
In [39]: ser.mean()
Out[39]: -0.6669999808073044
In [40]: ser + ser
Out[40]:
0 -3.09
1 0.422
2 <NA>
dtype: float[pyarrow]
In [41]: ser > (ser + 1)
Out[41]:
0 False
1 False
2 <NA>
dtype: bool[pyarrow]
In [42]: ser.dropna()
Out[42]:
0 -1.545
1 0.211
dtype: float[pyarrow]
In [43]: ser.isna()
Out[43]:
0 False
1 False
2 True
dtype: bool
In [44]: ser.fillna(0)
Out[44]:
0 -1.545
1 0.211
2 0.0
dtype: float[pyarrow]
In [45]: ser_str = pd.Series(["a", "b", None], dtype=pd.ArrowDtype(pa.string()))
In [46]: ser_str.str.startswith("a")
Out[46]:
0 True
1 False
2 <NA>
dtype: bool[pyarrow]
In [47]: from datetime import datetime
In [48]: pa_type = pd.ArrowDtype(pa.timestamp("ns"))
In [49]: ser_dt = pd.Series([datetime(2022, 1, 1), None], dtype=pa_type)
In [50]: ser_dt.dt.strftime("%Y-%m")
Out[50]:
0 2022-01
1 <NA>
dtype: string[pyarrow]
Чтение I/O
PyArrow также предоставляет функциональность чтения I/O, интегрированную в несколько читателей I/O pandas. Следующие функции предоставляют ключевое слово engine, которое может быть перенаправлено на PyArrow для ускорения чтения из источника I/O.
In [51]: import io
In [52]: data = io.StringIO("""a,b,c
....: 1,2.5,True
....: 3,4.5,False
....: """)
....:
In [53]: df = pd.read_csv(data, engine="pyarrow")
In [54]: df
Out[54]:
a b c
0 1 2.5 True
1 3 4.5 False
По умолчанию эти функции и все другие функции читателей I/O возвращают данные, основанные на NumPy. Эти читатели могут возвращать данные, основанные на PyArrow, указав параметр dtype_backend="pyarrow". Читателю не нужно устанавливать engine="pyarrow" для возврата данных, основанных на PyArrow.
In [55]: import io
In [56]: data = io.StringIO("""a,b,c,d,e,f,g,h,i
....: 1,2.5,True,a,,,,,
....: 3,4.5,False,b,6,7.5,True,a,
....: """)
....:
In [57]: df_pyarrow = pd.read_csv(data, dtype_backend="pyarrow")
In [58]: df_pyarrow.dtypes
Out[58]:
a int64[pyarrow]
b double[pyarrow]
c bool[pyarrow]
d string[pyarrow]
e int64[pyarrow]
f double[pyarrow]
g bool[pyarrow]
h string[pyarrow]
i null[pyarrow]
dtype: object
Несколько функций, не относящихся к чтению I/O, также могут использовать аргумент dtype_backend для возврата данных, основанных на PyArrow, включая:
© 2008–2022, AQR Capital Management, LLC, Lambda Foundry, Inc. and PyData Development Team
Licensed under the 3-clause BSD License.
https://pandas.pydata.org/pandas-docs/version/2.2.2/user_guide/pyarrow.html