Переведите PySpark Dataframe с массивами структур в классы Python и обратно - PullRequest
0 голосов
/ 22 января 2019

Я работаю с Zeppelin с фреймами данных Pyspark в среде Spark 2.3.2. И я должен поместить данные в классы и из них.

У меня проблемы с правильным добавлением массивов структур.

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

dfPre =  sqlContext.createDataFrame([
  (1,11,53,8),
  (1,12,54,7),
  (1,16,51,11),
  (2,21,63,13),
  (2,23,65,15),
],("ID", "itemID", "Attribute1", "Attribute2"))

import pyspark.sql.functions as f
df = dfPre.groupBy(f.col("ID")).agg(f.collect_list(f.struct(f.col("itemID"),f.col("Attribute1"),f.col("Attribute1"))).alias("items"))

df.printSchema()

root 
|-- ID: string (nullable = true) 
|-- items: array (nullable = true) 
| |-- element: struct (containsNull = true) 
| | |-- itemID: string (nullable = true) 
| | |-- Attribute1: double (nullable = true) 
| | |-- Attribute2: double (nullable = true)

df.show(2,False)

+---+------------------------------------------+ 
|ID |items                                     | 
+---+------------------------------------------+ 
|1  |[[11, 53, 11], [16, 51, 8], [12, 54, 7]]  | 
|2  |[[23, 65, 13], [21, 63, 15]]              | 
+---+------------------------------------------+

Классы, например, следующие

class Request:
    def __init__(self, data):
        self.ID = data["ID"]
        self.items = map(Items, data["items"])
    def __repr__(self):
        return "<ID:%s items:%s>" % (self.ID, self.items)
    def __str__(self):
        return "ID:%s items:%s" % (self.ID, self.items)

class Items: 
    def __init__(self, data):
        self.itemID = data["itemID"]
        self.Attribute1 = data["Attribute1"]
        self.Attribute2 = data["Attribute2"]
    def __repr__(self):
        return "<itemID:%s Attribute1:%s Attribute2:%s>" % (self.itemID, self.Attribute1, self.Attribute2)
    def __str__(self):
        return "itemID:%s Attribute1:%s Attribute2:%s" % (self.itemID, self.Attribute1, self.Attribute2)

Я попробовал следующее, чтобы получить массив в классе:

data = df.toPandas()
row = 0

ID = data['ID'][row]

itemList =[]
for i in range(len(data['items'][row])):
    itemList.append({"itemID": data['items'][row][i]['itemID'],
        "Attribute1": data['items'][row][i]['Attribute1'],
        "Attribute2": data['items'][row][i]['Attribute2']    })

items = {'items': itemList}

requestDataDict = {"ID": ID,"items": itemList}
request = Request(requestDataDict)

Но либо я не передаю массив должным образом, либо я просто не могу снова вывести его из класса.

print(request)

>> ID:102 items:<map object at 0x7fb54e234cf8>

def classExport(request):
    return request.items

test = classExport(request)

z.show(test)

>> <map object at 0x7fb54e234cf8>

В конце я хотел бы получить первую строку исходного кадра данных из класса.

Заранее спасибо

1 Ответ

0 голосов
/ 23 января 2019

Я сам нашел решение:

Хотя я сделал печатными элементы класса и элементы атрибута класса Request, сам объект карты не имеет хорошего способа печати. ​​

Но части карты могут быть напечатаны, поскольку они являются экземплярами элементов класса:

for x in test:
    print(x)

> itemID:16 Attribute1:51 Attribute2:11 
> itemID:11 Attribute1:53 Attribute2:8 
> itemID:12 Attribute1:54 Attribute2:7

Если определение класса Request изменяется так, что объект карты преобразуется в список, он можетпечататься с начала:

self.items = list(map(Items, data["items"]))

Выходная информация изменится на:

print(request)

> ID:1 items:[<itemID:16 Attribute1:51 Attribute2:11>, <itemID:11 Attribute1:53 Attribute2:8>, <itemID:12 Attribute1:54 Attribute2:7>]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...