从字典列表和列表理解中生成数据框很慢
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()
我正在尝试从字典列表生成数据框。字典列表是通过引用对象的列表理解生成的。
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()