Преобразование списка объектов в простой вектор? - PullRequest
0 голосов
/ 03 июля 2018

Я работаю с очень значительным объемом данных в Python и выполняю циклы в очень больших списках объектов класса. Очевидно, это занимает вечность, и я понимаю, что лучшее решение - это векторизовать мои списки, используя массивы. Однако я не смог найти метод, который позволил бы мне преобразовать мои списки объектов в нужные мне векторы.

Если у меня есть список, скажем, с 5 экземплярами класса «предложения», и эти объекты имеют такие атрибуты, что каждый экземпляр в списке выглядит примерно так:

{
    text: "I liked this phone.",
    rating: 5.0,
    positive: True
}

есть ли способ превратить это в простой вектор 5x3, где каждая строка [0] даст мне текст объекта?

Ответы [ 2 ]

0 голосов
/ 06 июля 2018

В своем классе объектов я создал метод as_dict (), который возвращал объект в виде словаря. Оттуда я применил словарную версию каждого из моих объектов к фрейму данных pandas, затем вызвал as_matrix (), чтобы получить его в виде массива. Казалось бы, сделать трюк!

0 голосов
/ 03 июля 2018

Таким образом, ваш объект представляет собой словарь, подобный:

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, хотя и несколько медленнее, чем в автономном или полностью числовом массиве.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...