将Pandas DataFrame转换为对象列表

21

我想将一个Pandas DataFrame转换为对象列表。

这是我的类:

class Reading:

    def __init__(self):
        self.HourOfDay: int = 0
        self.Percentage: float = 0

我研究了一下.to_dict,所以我尝试了一下

df.to_dict(into=Reading)

但它返回了

TypeError: unsupported type

我不想要元组或字典的列表,而是一个读数(Readings)的列表。到目前为止,我找到的每个问题似乎都是关于这两种情况的。但是我想要自己定义的类型对象。

谢谢

3个回答

24

选项1:使Reading继承自collections.MutableMapping,并实现该基类的必要方法。看起来是很多工作。

选项2:在列表推导式中调用Reading()

>>> import pandas as pd
>>> 
>>> df = pd.DataFrame({
...     'HourOfDay': [5, 10],
...     'Percentage': [0.25, 0.40]
... })
>>> 
>>> class Reading(object):
...     def __init__(self, HourOfDay: int = 0, Percentage: float = 0):
...         self.HourOfDay = int(HourOfDay)
...         self.Percentage = Percentage
...     def __repr__(self):
...         return f'{self.__class__.__name__}> (hour {self.HourOfDay}, pct. {self.Percentage})'
... 
>>> 
>>> readings = [Reading(**kwargs) for kwargs in df.to_dict(orient='records')]
>>> 
>>> 
>>> readings
[Reading> (hour 5, pct. 0.25), Reading> (hour 10, pct. 0.4)]

来自文档:

into:返回值中所有 Mapping 类型的集合。可以是实际类或您想要的映射类型的空实例。如果您想要一个 collections.defaultdict,则必须传递初始化。


你的回答完美地满足了我的需求!!非常感谢!!只是解释一下:我正在尝试将一些数据框转换为“对象”格式,以便将它们用作OpenOffice模板的“数据”,使用py3o.template库......顺便问一下,有没有办法自动初始化“列”类? - silvio
1
这应该被标记为有效答案。 - linSESH
@linSESH 我不再使用Python,并且当我提出这个问题时我还是一个初学者。鉴于这个问题已经变得如此受欢迎,如果您能向我解释为什么这个答案比被接受的答案更好,我将很乐意接受这个答案。 - zola25
@zola25 它提出了2个解决方案,我认为这两个都比被接受的更好。第二个方案相同,只是更加优雅。 - linSESH
@linSESH 感谢您的建议,在反思后我认为最近的答案是最好的。 - zola25

19

如果您有一个具有两列HourOfDay和Percentage的数据框,并且您的类具有参数化构造函数,您可以像这样定义对象列表:

使用您的类的参数化构造函数,您可以定义一个由HourOfDay和Percentage组成的元组列表,例如:

 class Reading:

   def __init__(self, h, p):
       self.HourOfDay = h 
       self.Percentage = p 

 listOfReading= [(Reading(row.HourOfDay,row.Percentage)) for index, row in df.iterrows() ]  

这种更通用的方法对我很有效 https://dev59.com/A18e5IYBdhLWcg3w4dmk#75420677 - captonssj

9

最好的方法是通过参数初始化类,如下所示:

 class Reading:
   def __init__(self, h, p):
       self.HourOfDay = h 
       self.Percentage = p 

接下来,为了创建一个读取列表,您可以使用以下函数,其将DataFrame作为参数:

 def reading_list(df:pd.DataFrame)->list:
    return list(map(lambda x:Reading(h=x[0],p=x[1]),df.values.tolist()))

即使数据集很大,执行速度也很快。


2
这个速度真是太快了!我刚从reading_objects = reading_df.progress_apply(lambda row: Reading(*row.to_list()), axis=1)转换过来,速度提升了4倍!(progress_apply是带有tqdm进度条的apply函数,而我仍然在df.values.tolist()周围使用tqdm()函数,所以不可能是它的原因)。 - Ben
2
我很惊讶这不是被接受的答案。优雅而且非常快速。 - DavidWalker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接