web-dev-qa-db-fra.com

Construire une rangée à partir d'un dict dans pySpark

J'essaie de créer dynamiquement une ligne dans pySpark 1.6.1, puis de la construire dans une trame de données. L'idée générale est d'étendre les résultats de describe pour inclure, par exemple, le biais et le kurtosis. Voici ce que je pensais que cela devrait fonctionner:

from pyspark.sql import Row

row_dict = {'C0': -1.1990072635132698,
            'C3': 0.12605772684660232,
            'C4': 0.5760856026559944,
            'C5': 0.1951877800894315,
            'C6': 24.72378589441825,
            'summary': 'kurtosis'}

new_row = Row(row_dict)

Mais cela renvoie TypeError: sequence item 0: expected string, dict found ce qui est une erreur assez claire. Ensuite, j'ai trouvé que si je définissais d'abord les champs Row, je pouvais utiliser un dict:

r = Row('summary', 'C0', 'C3', 'C4', 'C5', 'C6')
r(row_dict)
> Row(summary={'summary': 'kurtosis', 'C3': 0.12605772684660232, 'C0': -1.1990072635132698, 'C6': 24.72378589441825, 'C5': 0.1951877800894315, 'C4': 0.5760856026559944})

Ce serait une belle étape, sauf qu'il ne semble pas que je puisse spécifier dynamiquement les champs dans Row. J'ai besoin que cela fonctionne pour un nombre inconnu de lignes avec des noms inconnus. Selon la documentation, vous pouvez réellement aller dans l'autre sens:

>>> Row(name="Alice", age=11).asDict() == {'name': 'Alice', 'age': 11}
True

Il semble donc que je devrais être en mesure de le faire. Il semble également que certaines fonctionnalités obsolètes d'anciennes versions le permettent, par exemple ici . Y a-t-il un équivalent plus actuel qui me manque?

23
Jeff

Vous pouvez utiliser le déballage des arguments de mots clés comme suit:

Row(**row_dict)

## Row(C0=-1.1990072635132698, C3=0.12605772684660232, C4=0.5760856026559944, 
##     C5=0.1951877800894315, C6=24.72378589441825, summary='kurtosis')

Il est important de noter qu'il trie les données en interne par clé pour résoudre problèmes avec les anciennes Python .

30
zero323

Si le dict n'est pas aplati, vous pouvez le convertir récursivement en ligne.

def as_row(obj):
    if isinstance(obj, dict):
        dictionary = {k: as_row(v) for k, v in obj.items()}
        return Row(**dictionary)
    Elif isinstance(obj, list):
        return [as_row(v) for v in obj]
    else:
        return obj
2
ryan