繁体   English   中英

Python pandas:从 dataframe 的每一行构造列表数据类对象

[英]Python pandas: construct list dataclass objects from each row of a dataframe

一个一致的答案似乎是避免在使用 Pandas 时遍历行。我想了解在以下情况下如何执行此操作。

from typing import List

@dataclass
class Person:
    id: int
    name: str
    age: int

persons_df = pd.DataFrame(data={'id': [1, 2, 3], 'name': ['A', 'B', 'C'], 'age': [32, 44, '86']})

persons_list: List[Person] = [] #populate this list with Person objects, created from the dataframe above

# my approach is to use iterrows()
for row in persons_df.itertuples():
    person = Person(row.id, row.name, int(row.age)) # type: ignore
    plist.append(person)

我想找到一个可以避免 iterrows 的选项,如果可能的话,以内置某种类型安全的方式完成(避免 mypy 忽略注释)。

谢谢!

我不确定这是否是您正在寻找的,但也许这会有所帮助:

import pandas as pd
df = pd.DataFrame(data={'id': [1, 2, 3], 'name': ['A', 'B', 'C'], 'age': [32, 44, '86']})

class Person:
    def __init__(self, lst):
        self.id = lst[0]
        self.name = lst[1]
        self.age = lst[2]

df.apply(Person, axis=1).tolist()

出去:

[<__main__.Person at 0x176eee70608>,
 <__main__.Person at 0x176eee704c8>,
 <__main__.Person at 0x176eee70388>]

我添加了一个新的答案,因为问题的标题是map dataframe rows to a list of dataclass objects ,这还没有得到解决。

要返回数据类,我们可以稍微改进@Andreas answer ,而不需要额外的构造函数接收列表。 我们只需要使用 Python 传播运营商。

我看到两种映射方式:

  1. dataframe 列名匹配数据 class 字段名。 在这种情况下,我们可以向 map 查询我们的行作为一组关键字 arguments: df.apply(lambda row: MyDataClass(**row), axis=1)
  2. dataframe 列名与数据 class 字段名匹配,但列顺序与数据类字段顺序匹配 在这种情况下,我们可以要求我们的行值作为有序列表 arguments 传递: df.apply(lambda row: MyDataClass(*row), axis=1)

例子:

  1. 定义与问题中相同的数据 class 和相同的 dataframe:
     from dataclasses import dataclass @dataclass class Person: id: int name: str age: int import pandas df = pandas.DataFrame(data={ 'id': [1, 2, 3], 'name': ['A', 'B', 'C'], 'age': [32, 44, '86'] })
  2. 基于列顺序的转换:
     persons = df.apply(lambda row: Person(*row), axis=1)
  3. 基于列名的转换(为更好的测试打乱了列顺序):
     persons = df[['age', 'id', 'name']].apply(lambda row: Person(**row), axis=1)
  4. 现在,我们可以验证我们的结果。 在上述两种情况下:
    • 这个片段:
       print(type(persons)) print(persons)
    • 印刷:
       <class 'pandas.core.series.Series'> 0 Person(id=1, name='A', age=32) 1 Person(id=2, name='B', age=44) 2 Person(id=3, name='C', age='86') dtype: object

警告:

  • 我不知道这个解决方案的性能
  • 不会强制执行任何类型检查(看看最后打印的人:它的年龄是一个文本)。 由于默认情况下 Python 不强制键入,因此这种快速解决方案不会带来任何额外的安全性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM