Создание Pandas DataFrame с массивом numpy, содержащим несколько типов

Я хочу создать фреймворк pandas со значениями по умолчанию, равными нулю, но один столбец целых чисел и другой поплавков. Я могу создать массив numpy с правильными типами, см. Ниже переменную values. Однако, когда я передаю это в конструктор dataframe, он возвращает значения NaN (см. Ниже df). Я имею в виду нетипизированный код, который возвращает массив поплавков (см. df2)

import pandas as pd
import numpy as np

values = np.zeros((2,3), dtype='int32,float32')
index = ['x', 'y']
columns = ['a','b','c']

df = pd.DataFrame(data=values, index=index, columns=columns)
df.values.dtype

values2 = np.zeros((2,3))
df2 = pd.DataFrame(data=values2, index=index, columns=columns)
df2.values.dtype

Любые предложения по созданию блока данных?

Ответ 1

Вот несколько вариантов, которые вы могли бы выбрать:

import numpy as np
import pandas as pd

index = ['x', 'y']
columns = ['a','b','c']

# Option 1: Set the column names in the structured array dtype 
dtype = [('a','int32'), ('b','float32'), ('c','float32')]
values = np.zeros(2, dtype=dtype)
df = pd.DataFrame(values, index=index)

# Option 2: Alter the structured array column names after it has been created
values = np.zeros(2, dtype='int32, float32, float32')
values.dtype.names = columns
df2 = pd.DataFrame(values, index=index, columns=columns)

# Option 3: Alter the DataFrame column names after it has been created
values = np.zeros(2, dtype='int32, float32, float32')
df3 = pd.DataFrame(values, index=index)
df3.columns = columns

# Option 4: Use a dict of arrays, each of the right dtype:
df4 = pd.DataFrame(
    {'a': np.zeros(2, dtype='int32'),
     'b': np.zeros(2, dtype='float32'),
     'c': np.zeros(2, dtype='float32')}, index=index, columns=columns)

# Option 5: Concatenate DataFrames of the simple dtypes:
df5 = pd.concat([
    pd.DataFrame(np.zeros((2,), dtype='int32'), columns=['a']), 
    pd.DataFrame(np.zeros((2,2), dtype='float32'), columns=['b','c'])], axis=1)

# Option 6: Alter the dtypes after the DataFrame has been formed. (This is not very efficient)
values2 = np.zeros((2, 3))
df6 = pd.DataFrame(values2, index=index, columns=columns)
for col, dtype in zip(df6.columns, 'int32 float32 float32'.split()):
    df6[col] = df6[col].astype(dtype)

Каждый из вышеперечисленных вариантов дает тот же результат

   a  b  c
x  0  0  0
y  0  0  0

с dtypes:

a      int32
b    float32
c    float32
dtype: object

Почему pd.DataFrame(values, index=index, columns=columns) создает DataFrame с NaN:

values - это структурированный массив с именами столбцов f0, f1, f2:

In [171]:  values
Out[172]: 
array([(0, 0.0, 0.0), (0, 0.0, 0.0)], 
      dtype=[('f0', '<i4'), ('f1', '<f4'), ('f2', '<f4')])

Если вы передадите аргумент columns=['a', 'b', 'c'] в pd.DataFrame, то Pandas будет искать столбцы с этими именами в структурированном массиве values. Когда эти столбцы не найдены, Pandas помещает NaN в DataFrame для представления отсутствующих значений.