6
votes

PyArrow: stocker la liste des dictionnaires dans le parquet à l'aide de types imbriqués

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.


0 commentaires

3 Réponses :


2
votes

À 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')


0 commentaires

-1
votes

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  entrez la description de l'image ici


0 commentaires

0
votes

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


0 commentaires