Je souhaite stocker la trame de données pandas suivante dans un fichier parquet en utilisant PyArrow:
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "table.pxi", line 930, in pyarrow.lib.Table.from_pandas File "/anaconda3/lib/python3.6/site-packages/pyarrow/pandas_compat.py", line 371, in dataframe_to_arrays convert_types)] File "/anaconda3/lib/python3.6/site-packages/pyarrow/pandas_compat.py", line 370, in <listcomp> for c, t in zip(columns_to_convert, File "/anaconda3/lib/python3.6/site-packages/pyarrow/pandas_compat.py", line 366, in convert_column return pa.array(col, from_pandas=True, type=ty) File "array.pxi", line 177, in pyarrow.lib.array File "error.pxi", line 77, in pyarrow.lib.check_status File "error.pxi", line 87, in pyarrow.lib.check_status pyarrow.lib.ArrowTypeError: Unknown list item type: struct<>
Le type de la colonne field
est une liste de dictionnaires: p>
table = pa.Table.from_pandas(df, schema=schema, preserve_index=False)
Je définis d'abord le schéma PyArrow correspondant:
import pyarrow as pa schema = pa.schema([pa.field('field', pa.list_(pa.struct([])))])
Ensuite, j'utilise from_pandas ()
:
field 0 [{}, {}]
Ceci lève l'exception suivante:
import pandas as pd df = pd.DataFrame({'field': [[{}, {}]]})
Est-ce que je fais quelque chose de mal ou n'est-ce pas pris en charge par PyArrow?
J'utilise pyarrow 0.9.0, pandas 23.4, python 3.6.
3 Réponses :
À partir de maintenant, l'utilisation d'un mélange de listes et de structures comme type de données de colonne est une fonctionnalité non implémentée dans Apache Arrow (la bibliothèque sous-jacente de PyArrow). Ce numéro Jira suit la progression du sujet.
Avec PyArrow 0.15.0, il est déjà possible de créer une table pyarrow à partir d'une dataframe pandas avec des types imbriqués, mais il n'est pas possible de sauvegarder la table dans un fichier parquet (ou de la reconvertir en dataframe pandas): p>
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/tmp/bla.py", line 11, in <module> pyarrow.parquet.write_table(table, 'test.parquet') File "/anaconda3/lib/python3.7/site-packages/pyarrow/parquet.py", line 1344, in write_table writer.write_table(table, row_group_size=row_group_size) File "/anaconda3/lib/python3.7/site-packages/pyarrow/parquet.py", line 474, in write_table self.writer.write_table(table, row_group_size=row_group_size) File "pyarrow/_parquet.pyx", line 1375, in pyarrow._parquet.ParquetWriter.write_table File "pyarrow/error.pxi", line 86, in pyarrow.lib.check_status pyarrow.lib.ArrowNotImplementedError: Level generation for Struct not supported yet
import pandas as pd import pyarrow as pa import pyarrow.parquet df = pd.DataFrame({'field': [[{'a': 1}, {'a': 2}]]}) schema = pa.schema( [pa.field('field', pa.list_(pa.struct([('a', pa.int64())])))]) table = pa.Table.from_pandas(df, schema=schema, preserve_index=False) pyarrow.parquet.write_table(table, 'test.parquet')
J'ai pu enregistrer des dataframes pandas qui ont des tableaux dans des colonnes en tant que parquet et les relire du parquet aux dataframes en convertissant les dtypes dataframe de l'objet en str.
def mapTypes(x): return {'object': 'str', 'int64': 'int64', 'float64': 'float64', 'bool': 'bool', 'datetime64[ns, ' + timezone + ']': 'datetime64[ns, ' + timezone + ']'}.get(x,"str") # string is default if type not mapped table_names = [x for x in df.columns] table_types = [mapTypes(x.name) for x in df.dtypes] parquet_table = dict(zip(table_names, table_types)) df_pq = df.astype(parquet_table) import awswrangler as wr
wr.s3.to_parquet (df = df_pq, path = path, dataset = True, database = 'test', mode = 'overwrite', table = table.lower (), partition_cols = ['realmid'], sanitize_columns = True )
La photo ci-dessous montre la lecture d'un fichier parquet stocké dans s3 vers dataframe à l'aide de la bibliothèque AWS datawrangler, j'ai également fait cela avec pyarrow
Voici un extrait de code pour reproduire ce bug:
pip3 install pyarrow==2.0.0
Notez que de pandas à plume, rien ne casse, mais une fois que la dataframe est chargée à partir de plume et que l'on essaie d'y écrire, puis ça casse.
Pour résoudre ce problème, il suffit de mettre à jour pyarrow 2.0.0:
#!/usr/bin/env python3 import pandas as pd # type: ignore def main(): """Main function""" df = pd.DataFrame() df["nested"] = [[dict()] for i in range(10)] df.to_feather("test.feather") print("Success once") df = pd.read_feather("test.feather") df.to_feather("test.feather") if __name__ == "__main__": main()
Versions pyarrow disponibles à partir du 16/11/2020:
0.9.0, 0.10.0, 0.11.0, 0.11.1, 0.12.0, 0.12.1, 0.13.0, 0.14.0, 0.15.1, 0.16.0, 0.17.0, 0.17.1 , 1.0.0, 1.0.1, 2.0.0