Преобразование объекта класса Python в DataFrame

1

Как преобразовать объект класса Python с полями, в которых создаются другие классы, в DataFrame? Я попробовал следующий код ниже, но он не работает.

Я могу заставить его работать, когда self.address = Address() и self.agency_contact_info = ContactInfo()

class Address:
    def __init__(self):
        self.address_one = "address 1"
        self.address_two = "P.O. BOX 1"                  

class ContactInfo:
    def __init__(self):
        self.person_name = "Me"
        self.phone_number = "999-999-9999"    

class AgencyRecord:
    def __init__(self):
        self.agency_code = "00"
        self.agency_id = "000"
        self.agency_name = "Some Agency"
        self.address = Address()
        self.agency_contact_info = ContactInfo()            

def create_data():
    data = {}

    for i in range(0, 3):
        alc = AgencyRecord()                    
        data[i] = alc   

    column_list = [
        'agency_code', 'agency_id', 'agency_name', 
        'address_one', 'address_two', 'person_name', 'phone_number'
    ]

    spark.createDataFrame(
        list(data.values()),
        column_list
    ).createOrReplaceTempView("MyTempTable")
Теги:
apache-spark
apache-spark-sql
pyspark

1 ответ

0
Лучший ответ

Цитирую себя снова:

Я считаю полезным думать об аргументе createDataFrame() как о списке [iterables], где каждая запись в списке соответствует строке в DataFrame, а каждый элемент [iterable] соответствует столбцу.


Поэтому вам необходимо преобразовать каждый из ваших объектов в целое число, где каждый элемент соответствует столбцам в column_list.

Я не обязательно одобрил бы это (там почти наверняка лучший способ), но вот один хакерский подход, который вы можете предпринять, чтобы соответствующим образом изменить свой код:

Вы можете воспользоваться тем фактом, что объекты python имеют self.__dict__ который вы можете использовать для получения параметров по имени. Сначала обновите свой класс AgencyRecord чтобы получить поля из классов Address и ContactInfo:

class AgencyRecord:
    def __init__(self):
        self.agency_code = "00"
        self.agency_id = "000"
        self.agency_name = "Some Agency"
        self.address = Address()
        self.agency_contact_info = ContactInfo()

        # makes the variables of the contained classes members of this class
        self.__dict__.update(self.address.__dict__)
        self.__dict__.update(self.agency_contact_info.__dict__)

Теперь мы можем ссылаться на каждый столбец в column_list по имени для любого экземпляра AgencyRecord.

Измените create_data следующим образом (я также изменил это, чтобы вернуть DataFrame вместо регистрации временного представления)

def create_data():
    data = {}

    for i in range(0, 3):
        alc = AgencyRecord()                    
        data[i] = alc   

    column_list = [
        'agency_code', 'agency_id', 'agency_name', 
        'address_one', 'address_two', 'person_name', 'phone_number'
    ]

    values = [
        [data[record].__dict__[c] for c in column_list]
        for record in data
    ]

    return spark.createDataFrame(values, column_list)

Теперь вы можете сделать:

temp_df = create_data()
temp_df.show()
#+-----------+---------+-----------+-----------+-----------+-----------+------------+
#|agency_code|agency_id|agency_name|address_one|address_two|person_name|phone_number|
#+-----------+---------+-----------+-----------+-----------+-----------+------------+
#|         00|      000|Some Agency|  address 1| P.O. BOX 1|         Me|999-999-9999|
#|         00|      000|Some Agency|  address 1| P.O. BOX 1|         Me|999-999-9999|
#|         00|      000|Some Agency|  address 1| P.O. BOX 1|         Me|999-999-9999|
#+-----------+---------+-----------+-----------+-----------+-----------+------------+
  • 0
    Можно упростить data = {i: AgencyRecord() for i in range(3)}
  • 0
    @ cricket_007 конечно, но я просто скопировал и вставил эту часть кода OP.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню