2015-03-25 3 views
0

У меня есть кадр данных pandas, который имеет столбец, который содержит кортежи, состоящие из двух поплавков, например. (1.1,2.2). Я хочу иметь возможность создавать массив, содержащий первый элемент каждого кортежа. Я мог бы пройти через каждую строку и получить первый элемент каждого кортежа, но в dataframe содержится почти 4 миллиона записей, и такой подход очень медленный. Ответ на Satoru на SO (stackoverflow.com/questions/6454894/reference-an-element-in-a-list-of-tuples) предлагает использовать следующий механизм:Доступ к первым элементам в массиве numpy кортежей

>>> import numpy as np 
>>> arr = np.array([(1.1,2.2),(3.3,4.4),(5.5,6.6),(7.7,8.8)]) 
>>> arr 
array([[ 1.1, 2.2], 
     [ 3.3, 4.4], 
     [ 5.5, 6.6], 
     [ 7.7, 8.8]]) 
>>> arr[:,0] 
array([ 1.1, 3.3, 5.5, 7.7]) 

Так что работает отлично и будет быть абсолютно идеальным для моих нужд. Однако проблема возникает, когда я пытаюсь создать массив numpy из фреймворка pandas. В этом случае вышеупомянутое решение терпит неудачу с множеством ошибок. Например:

>>> import numpy as np 
>>> import pandas as pd 
>>> df = pd.DataFrame({'other':[0,0,0,1,1],'point':[(1.1,2.2),(3.3,4.4),(5.5,6.6),(7.7,8.8),(9.9,0.0)]}) 
>>> df 
    other  point 
0  0 (1.1, 2.2) 
1  0 (3.3, 4.4) 
2  0 (5.5, 6.6) 
3  1 (7.7, 8.8) 
4  1 (9.9, 0.0) 
>>> arr2 = np.array(df['point']) 
>>> arr2 
array([(1.1, 2.2), (3.3, 4.4), (5.5, 6.6), (7.7, 8.8), (9.9, 0.0)], dtype=object) 
>>> arr2[:,0] 
IndexError: too many indices for array 

В качестве альтернативы:

>>> arr2 = np.array([df['point']]) 
>>> arr2 
array([[[1.1, 2.2], 
     [3.3, 4.4], 
     [5.5, 6.6], 
     [7.7, 8.8], 
     [9.9, 0.0]]], dtype=object) 
>>> arr2[:,0] 
array([[1.1, 2.2]], dtype=object) # Which is not what I want! 

Что-то, кажется, идет не так, когда я передавать данные с пандами dataframe в Numpy массив - но я понятия не имею, что. Любые предложения были бы с благодарностью получены.

ответ

2

Начиная с dataframe, я могу извлечь (5,2) массив с:

In [68]: df=pandas.DataFrame({'other':[0,0,0,1,1],'point':[(1.1,2.2),(3.3,4.4),(5.5,6.6),(7.7,8.8),(9.9,0.0)]}) 

In [69]: np.array(df['point'].tolist()) 
Out[69]: 
array([[ 1.1, 2.2], 
     [ 3.3, 4.4], 
     [ 5.5, 6.6], 
     [ 7.7, 8.8], 
     [ 9.9, 0. ]]) 

df['point'] серия панды.

df['point'].values возвращает массив формы (5,) и dtype object. I

array([(1.1, 2.2), (3.3, 4.4), (5.5, 6.6), (7.7, 8.8), (9.9, 0.0)], dtype=object) 

Это, по сути, массив кортежей. Настоящие кортежи, а не структурированный массив tuple-look-a-likes. Массив фактически содержит указатели на кортежи, которые еще находятся в памяти. Его форма (5,) - это 1-й массив, поэтому попытка индексирования, как будто это 2d, даст вам слишком много ошибок. np.array([df['point']]) просто обертывает его в другом измерении, не обращаясь к проблеме dtype основного объекта.

tolist() преобразует его в список кортежей, из которого вы можете построить массив 2d.

Копирование данных из массивов объектов в массивы n-d не является тривиальным и требует неизменного копирования. Буферы данных совершенно разные, поэтому такие вещи, как astype, не работают.

+0

Очень четкое и краткое объяснение - спасибо большое. – user1718097

0
import numpy as np 
import pandas as pd 
df = pd.DataFrame({'other':[0,0,0,1,1],'point':[(1.1,2.2),(3.3,4.4),(5.5,6.6),(7.7,8.8),(9.9,0.0)]}) 
array = df['point'].apply(lambda x: x[0]).values 
array 
# array([ 1.1, 3.3, 5.5, 7.7, 9.9]) 
+0

Спасибо за это решение. Это, безусловно, даст желаемый результат. Однако на самом деле он не затрагивает вопрос о том, почему импорт данных из фреймворка в массив numpy не работает. – user1718097

Смежные вопросы