Как мне преобразовать фрейм данных Python в массив NumPy

#python-3.x #pandas #numpy

#python-3.x #pandas #numpy

Вопрос:

Ниже приведен фрагмент, который преобразует данные в массив NumPy. Затем он преобразуется в фрейм данных Pandas, где я намереваюсь его обработать. Я пытаюсь преобразовать его обратно в массив NumPy. Я терплю неудачу в этом. Плохо.

 import pandas as pd
import numpy as np
from pprint import pprint

data = [
    ('2020-11-01 00:00:00', 1.0),
    ('2020-11-02 00:00:00', 2.0)
]
coordinatesType = [('timestamp', 'datetime64[s]'), ('value', '<f8')]

npArray = np.asarray(data, coordinatesType)
df = pd.DataFrame(data = npArray)

# do some pandas processing, then convert back to a numpy array

mutatedNpArray = df.to_numpy(coordinatesType)
pprint(mutatedNpArray)

# don't suply dtype for kicks
pprint(df.to_numpy())
 

Это дает crazytown:

 array([[('2020-11-01T00:00:00', 1.6041888e 18),
        ('1970-01-01T00:00:01', 1.0000000e 00)],
       [('2020-11-02T00:00:00', 1.6042752e 18),
        ('1970-01-01T00:00:02', 2.0000000e 00)]],
      dtype=[('timestamp', '<M8[s]'), ('value', '<f8')])
array([[Timestamp('2020-11-01 00:00:00'), 1.0],
       [Timestamp('2020-11-02 00:00:00'), 2.0]], dtype=object)
 

Я понимаю, что фрейм данных — это действительно причудливый массив NumPy под капотом, но я возвращаюсь к функции, которая принимает простой массив NumPy. Очевидно, что я неправильно обрабатываю dtypes и / или я не понимаю структуру данных внутри моего фрейма данных. Ниже показано, что ожидает вызываемая функция:

 [('2020-11-01T00:00:00', 1.000   ),
 ('2020-11-02T00:00:00', 2.000  )],
 dtype=[('timestamp', '<M8[s]'), ('value', '<f8')])
 

Я действительно не понимаю, как это сделать. Или что я должен делать вместо этого.

Помогите!


Как предложил @hpaul, я попробовал следующее:

 # ...
df = df.set_index('timestamp')

# do some pandas processing, then convert back to a numpy array

mutatedNpArray = df.to_records(coordinatesType)
# ...
 

Все хорошо!

Комментарии:

1. Ищите to_records метод. Не забудьте прочитать документы. Возможно, вы сможете указать dtype , как вы делали изначально.

Ответ №1:

Помимо to_records подхода, упомянутого в комментариях, вы можете сделать:

 df.apply(tuple, axis=1).to_numpy(coordinatesType)
 

Вывод:

 array([('2020-11-01T00:00:00', 1.), ('2020-11-02T00:00:00', 2.)],
      dtype=[('timestamp', '<M8[s]'), ('value', '<f8')])
 

Соображения:

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

Форма вашего исходного массива numpy (2,) , где каждое значение является кортежем. При создании фрейма данных оба df.shape и df.to_numpy() формы (2, 2) таковы, что dtype конструктор работает не так, как ожидалось. При преобразовании строк в кортежи в a pd.Series вы получаете исходную форму (2,) .