将对象列表转换为 pandas 数据框
Posted
技术标签:
【中文标题】将对象列表转换为 pandas 数据框【英文标题】:Converting a list of objects to a pandas dataframe 【发布时间】:2018-05-17 07:22:59 【问题描述】:如何?
class Person(object):
def __init__(self):
self.name = ""
self.year = 0
self.salary = 0
例如下面的作品,但我想有一个人员类的列表
import pandas as pd
import numpy as np
data = 'name': ['Alice', 'Bob', 'Charles', 'David', 'Eric'],
'year': [2017, 2017, 2017, 2017, 2017],
'salary': [40000, 24000, 31000, 20000, 30000]
df = pd.DataFrame(data, index = ['Acme', 'Acme', 'Bilbao', 'Bilbao', 'Bilbao'])
print(df)
【问题讨论】:
喜欢这个?我认为问题不清楚:data = 'persons': [Person() for _ in range(5)]
使用列表理解? data = ['name': person.name, 'year': person.year, 'salary': person.salary for person in person_list]
很抱歉给您带来了困惑。我有一个人员对象列表,我想从中创建一个数据框,以便数据框列是人员的属性。我该怎么做?
【参考方案1】:
这个怎么样?
这将获取所有(第一级)属性并将它们放入一个字典中,该字典可以直接加载到 Pandas DataFrame 中,这是我认为 OP 正在寻找的,这避免了更改类。
not attr.starswith("_")
用于避免将私有属性加载到 Pandas DataFrame 中。
import pandas as pd
class Person(object):
def __init__(self, name='', year=0, salary=0):
self.name = name
self.year = year
self.salary = salary
person1 = Person('john', 2017, 100)
person2 = Person('smith', 2016, 200)
person3 = Person('roger', 2016, 500)
person_list = [person1, person2, person3]
data = [attr: getattr(p,attr) for attr in dir(p) if not attr.startswith('_') for p in person_list ]
df = pd.DataFrame(data)
print(df)
name salary year
0 john 100 2017
1 smith 200 2016
2 roger 500 2016
【讨论】:
您应该在解决方案中添加更多信息。【参考方案2】:ayhan 的建议和您似乎想要的组合 - 您可以向您的 Person 类添加一个方法,将其转换为适合 Pandas DataFrame 构造函数的东西。
class Person(object):
def __init__(self, name='', year=0, salary=0):
self.name = name
self.year = year
self.salary = salary
def as_dict(self):
return 'name': self.name, 'year': self.year, 'salary': self.salary
person1 = Person('john', 2017, 100)
person2 = Person('smith', 2016, 200)
person3 = Person('roger', 2016, 500)
person_list = [person1, person2, person3]
df = pd.DataFrame([x.as_dict() for x in person_list])
print(df)
name salary year
0 john 100 2017
1 smith 200 2016
2 roger 500 2016
【讨论】:
为什么列顺序不同?应该是: 如何设置列顺序?名字应该在第一列,年份应该在中间,薪水在最后 将columns
arg 传递给构造函数:df=pd.DataFrame([x.as_dict() for x in person_list], columns=['name', 'year', 'salary'])
另外,为了完整起见,您可以使用内置的 python vars
函数而不是定义 as_dict
: [vars(x) for x in person_list]。
as_dict() 与 dict 几乎相同,所以 pd.DataFrame([x.__dict__ for x in person_list])
是另一种选择(好吧,在我尝试过的 Python 版本中)【参考方案3】:
首先,您应该修改您的__init__()
,因为您的版本只是将任何Person
对象的每个属性都设置为默认值,并且不允许用户设置它们。
然后您可以使用 zip()
函数在您的 data
字典中创建三组值,然后使用这些值创建 Person
实例
import pandas as pd
class Person:
def __init__(self, name='', year=0, salary=0):
self.name = name
self.year = year
self.salary = salary
data = 'name': ['Alice', 'Bob', 'Charles', 'David', 'Eric'],
'year': [2017, 2017, 2017, 2017, 2017],
'salary': [40000, 24000, 31000, 20000, 30000]
foo = [Person(name, year, salary) for name, year, salary in zip(data['name'], data['year'], data['salary'])]
df = pd.DataFrame(foo, index=['Acme']*2 + ['Bilbao']*3, columns=['Person'])
first_person = df['Person'].iloc[0]
print(first_person.name, first_person.year, first_person.salary)
输出:
Alice 2017 40000
【讨论】:
以上是关于将对象列表转换为 pandas 数据框的主要内容,如果未能解决你的问题,请参考以下文章