Таким образом, ваш объект представляет собой словарь, подобный:
In [49]: dd = {
...: 'text': "I liked this phone.",
...: 'rating': 5.0,
...: 'positive': True
...: }
Я мог бы создать массив dtype объекта, который содержит 5 копий этого словаря (или подобных объектов):
In [50]: arrO = np.empty((5,), object)
In [51]: dict(dd)
Out[51]: {'text': 'I liked this phone.', 'rating': 5.0, 'positive': True}
In [52]: for i in range(5):
...: arrO[i] = dict(dd)
...:
In [53]: arrO
Out[53]:
array([{'text': 'I liked this phone.', 'rating': 5.0, 'positive': True},
{'text': 'I liked this phone.', 'rating': 5.0, 'positive': True},
{'text': 'I liked this phone.', 'rating': 5.0, 'positive': True},
{'text': 'I liked this phone.', 'rating': 5.0, 'positive': True},
{'text': 'I liked this phone.', 'rating': 5.0, 'positive': True}],
dtype=object)
Но такой массив объектов очень похож на список - оба содержат указатели на объекты в других местах памяти:
In [54]: [dict(dd) for _ in range(5)]
Out[54]:
[{'text': 'I liked this phone.', 'rating': 5.0, 'positive': True},
{'text': 'I liked this phone.', 'rating': 5.0, 'positive': True},
{'text': 'I liked this phone.', 'rating': 5.0, 'positive': True},
{'text': 'I liked this phone.', 'rating': 5.0, 'positive': True},
{'text': 'I liked this phone.', 'rating': 5.0, 'positive': True}]
Итерации в списке быстрее. Большинство операций над массивом объектов включают итерации, за исключением таких вещей, как reshape
, которые не требуют доступа к отдельным элементам.
Другой вариант - создать структурированный массив.
Ключом к созданию структурированного массива является определение составного dtype
и предоставление данных в виде списка tuples
:
В словаре 3.6 порядок определен, поэтому values
дает желаемый порядок:
In [55]: tuple(dd.values())
Out[55]: ('I liked this phone.', 5.0, True)
In [56]: dt = np.dtype([('text','U30'),('rating',float),('positive',bool)])
In [57]: dt
Out[57]: dtype([('text', '<U30'), ('rating', '<f8'), ('positive', '?')])
Создать массив со списком кортежей:
In [58]: arrS = np.array([tuple(dd.values()) for _ in range(5)],dtype=dt)
In [59]: arrS
Out[59]:
array([('I liked this phone.', 5., True),
('I liked this phone.', 5., True),
('I liked this phone.', 5., True),
('I liked this phone.', 5., True),
('I liked this phone.', 5., True)],
dtype=[('text', '<U30'), ('rating', '<f8'), ('positive', '?')])
Доступ к полям по имени. Обратите внимание, что это массив 1d (5,) с 3 полями, а не массив (5,3):
In [60]: arrS['rating']
Out[60]: array([5., 5., 5., 5., 5.])
In [61]: arrS['positive']
Out[61]: array([ True, True, True, True, True])
Изменение значений полей:
In [62]: arrS['positive'] = [1,0,0,1,0]
In [63]: arrS['rating'] = np.arange(5)
In [64]: arrS
Out[64]:
array([('I liked this phone.', 0., True),
('I liked this phone.', 1., False),
('I liked this phone.', 2., False),
('I liked this phone.', 3., True),
('I liked this phone.', 4., False)],
dtype=[('text', '<U30'), ('rating', '<f8'), ('positive', '?')])
Мы можем сделать математику на числовых полях:
In [65]: np.sum(arrS['rating'])
Out[65]: 10.0
Использование логического поля в качестве маски:
In [66]: arrS[arrS['positive']]
Out[66]:
array([('I liked this phone.', 0., True),
('I liked this phone.', 3., True)],
dtype=[('text', '<U30'), ('rating', '<f8'), ('positive', '?')])
In [67]: arrS[~arrS['positive']]
Out[67]:
array([('I liked this phone.', 1., False),
('I liked this phone.', 2., False),
('I liked this phone.', 4., False)],
dtype=[('text', '<U30'), ('rating', '<f8'), ('positive', '?')])
Операции в структурированном массиве выполняются быстрее, чем в объекте dtype, хотя и несколько медленнее, чем в автономном или полностью числовом массиве.