Хотя pandas может создавать кадр данных из списка простым вызовом, это не значит, что он быстрый.
In [260]: alist =[{u'key_as_string': u'2019-01-16T00:00:00.000+05:30', u'key': 1
...: 547577000000, u'doc_count': 1},
...: {u'key_as_string': u'2019-01-17T00:00:00.000+05:30', u'key': 15
...: 47663400000, u'doc_count': 3},
...: {u'key_as_string': u'2019-01-18T00:00:00.000+05:30', u'key': 15
...: 47749800000, u'doc_count': 3},
...: {u'key_as_string': u'2019-01-19T00:00:00.000+05:30', u'key': 15
...: 47836200000, u'doc_count': 3}]
...:
In [261]: pd.DataFrame(alist)
Out[261]:
doc_count ... key_as_string
0 1 ... 2019-01-16T00:00:00.000+05:30
1 3 ... 2019-01-17T00:00:00.000+05:30
2 3 ... 2019-01-18T00:00:00.000+05:30
3 3 ... 2019-01-19T00:00:00.000+05:30
[4 rows x 3 columns]
In [262]: _.dtypes
Out[262]:
doc_count int64
key int64
key_as_string object
dtype: object
In [263]: timeit pd.DataFrame(alist)
694 µs ± 19.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
В своих комментариях я сосредоточился на доступе к словарям ключом, нозабыл, что мы можем быстро получить доступ ко всем значениям в виде списка.
In [264]: [tuple(d.values()) for d in alist]
Out[264]:
[('2019-01-16T00:00:00.000+05:30', 1547577000000, 1),
('2019-01-17T00:00:00.000+05:30', 1547663400000, 3),
('2019-01-18T00:00:00.000+05:30', 1547749800000, 3),
('2019-01-19T00:00:00.000+05:30', 1547836200000, 3)]
In [265]: timeit [tuple(d.values()) for d in alist]
1.43 µs ± 11.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
По сравнению с pandas
это невероятно быстро.
Я использовал tuple
, поэтому этот список можно было передать структурированномумассив:
In [266]: dt = np.dtype([('key_as_string', 'U40'),('doc_count', int),('id',int)]
...: )
In [267]: np.array([tuple(d.values()) for d in alist],dt)
Out[267]:
array([('2019-01-16T00:00:00.000+05:30', 1547577000000, 1),
('2019-01-17T00:00:00.000+05:30', 1547663400000, 3),
('2019-01-18T00:00:00.000+05:30', 1547749800000, 3),
('2019-01-19T00:00:00.000+05:30', 1547836200000, 3)],
dtype=[('key_as_string', '<U40'), ('doc_count', '<i8'), ('id', '<i8')])
In [268]: timeit np.array([tuple(d.values()) for d in alist],dt)
5.12 µs ± 34.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Или для преобразования строк в datetime
In [269]: dt1 = np.dtype([('key_as_string', 'datetime64[m]'),('doc_count', int),
...: ('id',int)])
In [270]: np.array([tuple(d.values()) for d in alist],dt1)
/usr/local/bin/ipython3:1: DeprecationWarning: parsing timezone aware datetimes is deprecated; this will raise an error in the future
#!/usr/bin/python3
Out[270]:
array([('2019-01-15T18:30', 1547577000000, 1),
('2019-01-16T18:30', 1547663400000, 3),
('2019-01-17T18:30', 1547749800000, 3),
('2019-01-18T18:30', 1547836200000, 3)],
dtype=[('key_as_string', '<M8[m]'), ('doc_count', '<i8'), ('id', '<i8')])
Это немного медленнее, но все же намного быстрее панд.
И получить доступ только к одномуключ по словарям:
In [273]: [d['doc_count'] for d in alist]
Out[273]: [1, 3, 3, 3]
In [274]: np.array([d['doc_count'] for d in alist])
Out[274]: array([1, 3, 3, 3])
In [275]: timeit np.array([d['doc_count'] for d in alist])
2.69 µs ± 126 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
И давайте проверим большой список:
In [308]: blist = alist * 1000
In [309]: timeit np.array([d['doc_count'] for d in blist])
430 µs ± 67.6 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [310]: timeit np.array([tuple(d.values()) for d in blist],dt)
2.18 ms ± 4.01 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [311]: timeit pd.DataFrame(blist)
5.6 ms ± 140 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Панды не выглядят так плохо!