2016-07-07 3 views
13

Я пытаюсь динамически построить строку в pySpark 1.6.1, а затем построить ее в dataframe. Общая идея состоит в том, чтобы расширить результаты describe, чтобы включить, например, перекос и эксцесс. Вот то, что я думал, что должно работать:Построение строки из dict в pySpark

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(name="Alice", age=11).asDict() == {'name': 'Alice', 'age': 11} 
True 

Так что, похоже, я должен быть в состоянии это сделать. Также представляется, что могут быть некоторые устаревшие функции из более старых версий, которые допускали это, например here. Есть ли более текущий эквивалент, который мне не хватает?

ответ

17

Вы можете использовать именованные аргументы распаковки следующим образом:

Row(**row_dict) 

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

Важно отметить, что internally sorts data by key обратиться problems with older Python versions.

+0

Действительно ли это из конкретной версии Python или это общее правило? Причина, по которой я прошу, связана с вашим [последним правлением] (https://stackoverflow.com/posts/38253641/revisions). – eliasah

+1

@eliasah Поскольку Spark всегда будет сортироваться внутри, это не имеет значения, что мы делаем до этого. И при обсуждении JIRA это не изменится, пока Spark не поддержит Python <3.6 (не скоро). 'OrderedDict' немного вводил в заблуждение, поэтому я удалил его. – zero323

+0

Хорошо спасибо! Это было началом моей путаницы. – eliasah

1

В случае, если 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 
Смежные вопросы