Построение строки из dict в pySpark
Я пытаюсь динамически строить строку в pySpark 1.6.1, а затем встраивать ее в dataframe. Общая идея состоит в том, чтобы расширить результаты describe
чтобы включить, например, перекос и эксцесс. Здесь то, что я думал, должно работать:
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)
Но это возвращает TypeError: sequence item 0: expected string, dict found
которая является довольно явной ошибкой. Затем я обнаружил, что если бы я сначала определял поля Row, я мог бы использовать 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})
Какой будет прекрасный шаг, за исключением того, что не кажется, что я могу динамически задавать поля в Row
. Мне нужно, чтобы это работало для неизвестного количества строк с неизвестными именами. Согласно документации, вы можете пойти по-другому:
>>> Row(name="Alice", age=11).asDict() == {'name': 'Alice', 'age': 11}
True
Поэтому мне кажется, что я должен это сделать. Также представляется, что могут быть некоторые устаревшие функции из более старых версий, которые допускали это, например, здесь. Есть ли более текущий эквивалент, который мне не хватает?
Ответы
Ответ 1
Вы можете использовать распаковку аргументов ключевых слов следующим образом:
Row(**row_dict)
## Row(C0=-1.1990072635132698, C3=0.12605772684660232, C4=0.5760856026559944,
## C5=0.1951877800894315, C6=24.72378589441825, summary='kurtosis')
Важно отметить, что он внутренне сортирует данные по ключевым словам для решения проблем со старыми версиями Python.
Ответ 2
Если dict не сглажен, вы можете преобразовать dict в Row рекурсивно.
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