Вы создали массив записей (также называемый структурированным массивом). В результате получается массив 1d с именованными столбцами (полями).
Для иллюстрации:
In [426]: df = pd.DataFrame(np.arange(12).reshape(4,3), columns=['A','B','C'])
In [427]: df
Out[427]:
A B C
0 0 1 2
1 3 4 5
2 6 7 8
3 9 10 11
In [428]: arr = df.to_records()
In [429]: arr
Out[429]:
rec.array([(0, 0, 1, 2), (1, 3, 4, 5), (2, 6, 7, 8), (3, 9, 10, 11)],
dtype=[('index', '<i8'), ('A', '<i8'), ('B', '<i8'), ('C', '<i8')])
In [430]: arr['A']
Out[430]: array([0, 3, 6, 9])
In [431]: arr.shape
Out[431]: (4,)
Мне кажется, to_records
имеет параметр для удаления поля индекса.
Или с помощью вашего метода:
In [432]:
In [432]: arr = np.rec.fromrecords(df, names=df.columns.tolist())
In [433]: arr
Out[433]:
rec.array([(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11)],
dtype=[('A', '<i8'), ('B', '<i8'), ('C', '<i8')])
In [434]: arr['A'] # arr.A also works
Out[434]: array([0, 3, 6, 9])
In [435]: arr.shape
Out[435]: (4,)
и многопользовательский доступ:
In [436]: arr[['A','C']]
Out[436]:
rec.array([(0, 2), (3, 5), (6, 8), (9, 11)],
dtype={'names':['A','C'], 'formats':['<i8','<i8'], 'offsets':[0,16], 'itemsize':24})
Обратите внимание, что отображение str
этого массива
In [437]: print(arr)
[(0, 1, 2) (3, 4, 5) (6, 7, 8) (9, 10, 11)]
показывает список кортежей, так же, как ваш np_arr
. Каждый кортеж является «записью». На дисплее repr
также отображается dtype
.
Вы не можете использовать оба способа, либо получить доступ к столбцам по имени, либо создать обычный массив numpy и получить доступ к столбцам по номеру. Доступ по имени / записи имеет смысл, когда столбцы представляют собой смесь типов dty - string, int, float. Если они все плавающие, и вы хотите выполнять вычисления по столбцам, лучше использовать цифру c dtype.
In [438]: arr = df.to_numpy()
In [439]: arr
Out[439]:
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])