从pandas转换为numpy时如何保留列名

use*_*956 6 python numpy pandas

根据这篇文章,我应该能够访问ndarray中列的名称作为a.dtype.names

但是,如果我将pandas DataFrame转换为带有df.as_matrix()或df.values的ndarray,则dtype.names字段为None.此外,如果我尝试将列名称分配给ndarray

X = pd.DataFrame(dict(age=[40., 50., 60.], sys_blood_pressure=[140.,150.,160.]))
print X
print type(X.as_matrix())# <type 'numpy.ndarray'>
print type(X.as_matrix()[0]) # <type 'numpy.ndarray'>

m = X.as_matrix()
m.dtype.names = list(X.columns)
Run Code Online (Sandbox Code Playgroud)

我明白了

ValueError: there are no fields defined
Run Code Online (Sandbox Code Playgroud)

更新:

我特别感兴趣的是矩阵只需要保存一个类型(它是一个特定数字类型的ndarray),因为我也想使用cython进行优化.(我怀疑numpy记录和结构化数组更难以处理,因为它们更自由地输入.)

实际上,我只想维护通过sci-kit预测器深层树的数组的column_name元数据.它的接口的.fit(X,y)和.predict(X)API不允许传递关于X和y对象之外的列标签的附加元数据.

Nic*_*eli 6

考虑DF如下所示:

X = pd.DataFrame(dict(one=['Strawberry', 'Fields', 'Forever'], two=[1,2,3]))
X
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

提供元组列表作为结构化数组的数据输入:

arr_ip = [tuple(i) for i in X.as_matrix()]
Run Code Online (Sandbox Code Playgroud)

有序的字段名称列表:

dtyp = np.dtype(list(zip(X.dtypes.index, X.dtypes)))
Run Code Online (Sandbox Code Playgroud)

在这里,X.dtypes.index为您提供列名称及其X.dtypes相应的dtypes,它们再次统一到元组列表中,并作为输入提供给要构造的dtype元素.

arr = np.array(arr_ip, dtype=dtyp)
Run Code Online (Sandbox Code Playgroud)

得到:

arr
# array([('Strawberry', 1), ('Fields', 2), ('Forever', 3)], 
#       dtype=[('one', 'O'), ('two', '<i8')])
Run Code Online (Sandbox Code Playgroud)

arr.dtype.names
# ('one', 'two')
Run Code Online (Sandbox Code Playgroud)


use*_*814 5

Pandas 数据框也有一个方便的to_records方法。演示:

X = pd.DataFrame(dict(age=[40., 50., 60.], 
                      sys_blood_pressure=[140.,150.,160.]))
m = X.to_records(index=False)
print repr(m)
Run Code Online (Sandbox Code Playgroud)

返回:

rec.array([(40.0, 140.0), (50.0, 150.0), (60.0, 160.0)], 
          dtype=[('age', '<f8'), ('sys_blood_pressure', '<f8')])
Run Code Online (Sandbox Code Playgroud)

这是一个“记录数组”,它是一个 ndarray 子类,它允许使用属性进行字段访问,例​​如m.age除了m['age'].

您可以通过构建视图将其作为常规浮点数组传递给 cython 函数:

m_float = m.view(float).reshape(m.shape + (-1,))
print repr(m_float)
Run Code Online (Sandbox Code Playgroud)

这使:

rec.array([[  40.,  140.],
           [  50.,  150.],
           [  60.,  160.]], 
          dtype=float64)
Run Code Online (Sandbox Code Playgroud)

请注意,为了使其工作,原始 Dataframe 必须为每一列都有一个 float dtype。为了确保使用m = X.astype(float, copy=False).to_records(index=False).