从字典列表和列表理解中生成数据框很慢

Generating a dataframe from list of dicts and list comprehension slow

我正在尝试从字典列表生成数据框。字典列表是通过引用对象的列表理解生成的。

import pandas as pd


class Foo:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    @property
    def rep(self):
        return {'a': self.a, 'b': self.b}


class Bar:
    def __init__(self):
        self.container = [Foo('1', '2'), Foo('2', '3'), Foo('3', '4')]

    def data(self):
        return [x.rep for x in self.container]


class Base:
    def __init__(self):
        self.all = {'A': [Bar(), Bar(), Bar()], 'B': [Bar(), Bar(), Bar()]}
        #

    def test(self):
        list_of_reps = []
        [list_of_reps.extend(b.data()) for bar in [self.all[x] for x in self.all] for b in bar]
        pd.DataFrame(list_of_reps)


if __name__ == '__main__':
    b = Base()
    b.test()

然后我使用基 class 来组合 Foo class 中的所有词典。这个数字可能是几千,随着列表的增长,我发现转换到数据框的速度很慢,Bar 中的 data() 方法也是如此。有没有更优化的生成方法?

I am trying to generate a dataframe from a list of dictionaries.

从某种意义上说,这肯定会很慢,因为 Python 对象的效率低于 Pandas Dataframe 中的一行。如果您可以避免每行创建一个对象,那将节省执行时间。

[self.all[x] for x in self.all]

这相当于self.all.values()

class Foo:

这可以替换为 namedtuple,这样更节省内存。这还可以让您避免在 Bar.data().

中进行迭代

为了提高内存效率,我会尽可能使用迭代器而不是列表。

以下是我将如何更改此示例:

import pandas as pd
from collections import namedtuple
import itertools

Foo = namedtuple("Foo", "a b")

class Bar:
    def __init__(self):
        self.container = [Foo('1', '2'), Foo('2', '3'), Foo('3', '4')]

    def data(self):
        return self.container


class Base:
    def __init__(self):
        self.all = {'A': [Bar(), Bar(), Bar()], 'B': [Bar(), Bar(), Bar()]}

    def test(self):
        all_bars = itertools.chain.from_iterable(self.all.values())
        reps_generator = (bar.data() for bar in all_bars)
        reps_flattened = itertools.chain.from_iterable(reps_generator)
        print(pd.DataFrame(reps_flattened))


if __name__ == '__main__':
    b = Base()
    b.test()