Преобразовать столбец списков в двумерный массив - PullRequest
0 голосов
/ 16 января 2019

Я делаю некоторые операции на фрейме данных Pandas. Для определенного столбца мне нужно преобразовать каждую ячейку в простой массив, что не сложно. Конечная цель - получить двумерный массив в результате всего столбца. Однако, когда я выполняю следующую операцию, я получаю одномерный массив, а внутренние массивы не распознаются.

df = pd.DataFrame({'col': ['abc', 'def']})
mapping = {v: k for k, v in enumerate('abcdef')}
df['new'] = df['col'].apply(lambda x: list(x))
df['new'].apply(lambda x: np.array([mapping[i] for i in x])).values

Это дает:

array([array([0, 1, 2]), array([3, 4, 5])], dtype=object)

и форма (2,) означает, что внутренние массивы не распознаются.

Если я сделаю s.reshape(2,-1), я получу (2,1) вместо (2,3) для фигуры.

Ценю любую помощь!


Пояснение:

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

Ответы [ 2 ]

0 голосов
/ 17 января 2019
In [2]: import pandas as pd
In [3]: df = pd.DataFrame({'col': ['abc', 'def']})
   ...: mapping = {v: k for k, v in enumerate('abcdef')}
   ...: df['new'] = df['col'].apply(lambda x: list(x))

In [7]: df['new']
Out[7]: 
0    [a, b, c]
1    [d, e, f]
Name: new, dtype: object
In [8]: df['new'].values
Out[8]: array([list(['a', 'b', 'c']), list(['d', 'e', 'f'])], dtype=object)

np.stack ведет себя очень похоже на np.array, объединяя элементы на новой начальной оси:

In [9]: np.stack(df['new'].values)
Out[9]: 
array([['a', 'b', 'c'],
       ['d', 'e', 'f']], dtype='<U1')

или по другой оси вы выбираете:

In [10]: np.stack(df['new'].values, axis=1)
Out[10]: 
array([['a', 'd'],
       ['b', 'e'],
       ['c', 'f']], dtype='<U1')

np.array также работает, если массив объектов превращается в список (как показывает @coldspeed):

In [11]: df['new'].values.tolist()
Out[11]: [['a', 'b', 'c'], ['d', 'e', 'f']]
In [12]: np.array(df['new'].values.tolist())
Out[12]: 
array([['a', 'b', 'c'],
       ['d', 'e', 'f']], dtype='<U1')

Что касается скорости, давайте сделаем больший массив:

In [16]: arr = np.frompyfunc(lambda x: np.arange(1000),1,1)(np.arange(1000))
In [17]: arr.shape
Out[17]: (1000,)
In [18]: np.stack(arr).shape
Out[18]: (1000, 1000)
In [20]: np.array(arr.tolist()).shape
Out[20]: (1000, 1000)

In [21]: timeit np.stack(arr).shape
5.24 ms ± 190 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [22]: timeit np.array(arr.tolist()).shape
4.45 ms ± 138 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

В основном то же самое, с небольшим перевесом к подходу np.array.

stack подобно vstack расширяет размеры каждого элемента по мере необходимости. Пропуск с concatenate немного быстрее:

In [27]: timeit np.concatenate(arr).reshape(-1,1000).shape
4.04 ms ± 12.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Это arr содержит массивы. Если вместо этого он содержит списки, то подход array(arr.tolist()) работает лучше (относительно), поскольку у него есть только один список (списков) для преобразования в массив. Подход stack должен сначала преобразовать каждый из подсписков в массивы.

0 голосов
/ 17 января 2019

Я думаю, что было бы лучше создать массив из значений списка напрямую.

 df
   col        new
0  abc  [a, b, c]
1  def  [d, e, f]

arr = np.array(df['new'].tolist())
arr
# array([['a', 'b', 'c'],
#        ['d', 'e', 'f']], dtype='<U1')

arr.shape
# (2, 3)

Большой отказ от ответственности: Это будет работать, только если у всех списков есть одинаковое количествоэлементы.Если нет, это будет означать, что они являются рваными массивами, и numpy не сможет использовать эффективный формат памяти для представления вашего массива (следовательно, dtype='object').

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