Давайте посмотрим на некоторые фрагменты кода:
import numpy as np
import pandas as pd
from copy import deepcopy as cp
N_objects = 10
N_samples = 10000
class SimpleClass:
def __init__(self,prop):
self.properties = prop
dict_of_objects = {'obj{}'.format(i):
SimpleClass({
'alice' : np.random.rand(N_samples),
'bob' : np.random.rand(N_samples)
}) for i in range(N_objects)}
def slow_update(dict_of_objects):
series_list = []
for obj in dict_of_objects.values():
test = pd.Series(obj.properties)
series_list.append(test)
return pd.DataFrame(series_list)
def med_update(dict_of_objects):
return pd.DataFrame([pd.Series(obj.properties) for obj in dict_of_objects.values()])
def fast_update(dict_of_objects):
keys = iter(dict_of_objects.values()).__next__().properties.keys()
return pd.DataFrame({k: [obj.properties[k] for obj in dict_of_objects.values()] for k in keys})
И с таймингами:
>>> %timeit slow_update(dict_of_objects)
2.88 ms ± 19.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
>>> %timeit med_update(dict_of_objects)
2.86 ms ± 23.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
>>> %timeit fast_update(dict_of_objects)
344 µs ± 17.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Быстрое обновление делает следующее:
- Захватитеполя из итератора с одним использованием
__next__
. - Построение полей с использованием списка.
- Построение структуры данных с использованием словарного понимания.
Это оВ 8 раз быстрее, чем большинство методов.
Редактировать: , как правильно указал @koPytok, fast_update
не будет работать, если атрибут properties
каждого объекта имеет разные ключи . Это стоит иметь в виду, если вы решите реализовать это для чего-то такого, как захват базы данных NoSQL - в MongoDB документы не должны иметь одни и те же поля (здесь поменяйте местами документ для объекта, поле для ключа).
Наслаждайтесь!