Python 从数据帧提取行时保留数据类型

Python 从数据帧提取行时保留数据类型,python,pandas,numpy,dataframe,dtype,Python,Pandas,Numpy,Dataframe,Dtype,从熊猫数据帧中提取单个行(例如,使用.loc或.iloc)将生成一个熊猫系列。但是,当处理数据框中的异构数据时(即数据框的列不都是相同的数据类型),这会导致行中不同列的所有值强制为单个数据类型,因为系列只能有一个数据类型。下面是一个简单的例子来说明我的意思: import numpy import pandas a = numpy.arange(5, dtype='i8') b = numpy.arange(5, dtype='u8')**2 c = numpy.arange(5, dtype

熊猫
数据帧
中提取单个(例如,使用
.loc
.iloc
)将生成一个
熊猫
系列
。但是,当处理
数据框
中的异构数据时(即
数据框
的列不都是相同的数据类型),这会导致行中不同列的所有值强制为单个数据类型,因为
系列
只能有一个数据类型。下面是一个简单的例子来说明我的意思:

import numpy
import pandas

a = numpy.arange(5, dtype='i8')
b = numpy.arange(5, dtype='u8')**2
c = numpy.arange(5, dtype='f8')**3
df = pandas.DataFrame({'a': a, 'b': b, 'c': c})
df.dtypes
# a      int64
# b     uint64
# c    float64
# dtype: object
df
#    a   b     c
# 0  0   0   0.0
# 1  1   1   1.0
# 2  2   4   8.0
# 3  3   9  27.0
# 4  4  16  64.0
df.loc[2]
# a    2.0
# b    4.0
# c    8.0
# Name: 2, dtype: float64
df.loc[2]
中的所有值都已转换为
float64


有没有一种不进行这种类型转换就提取行的好方法?我可以想象,例如返回一个,但我看不到创建这样一个数组的简单方法。

正如您已经意识到的,series不允许混合
数据类型。但是,如果将其数据类型指定为
对象
,则它允许混合数据类型。因此,您可以将数据帧的数据类型转换为
对象
。每一列都将在数据类型
对象中
,但每一个值仍保持其数据类型为
int
float

df1 = df.astype('O')

Out[10]:
   a   b   c
0  0   0   0
1  1   1   1
2  2   4   8
3  3   9  27
4  4  16  64

In [12]: df1.loc[2].map(type)
Out[12]:
a      <class 'int'>
b      <class 'int'>
c    <class 'float'>
Name: 2, dtype: object
另一种方法(但感觉有点粗糙):

您可以使用长度为1的切片器,而不是使用带有
loc
iloc
的整数。这将返回长度为1的数据帧,因此
iloc[0]
包含您的数据。e、 g

In[1] : row2 = df[2:2+1]
In[2] : type(row)
Out[2]: pandas.core.frame.DataFrame
In[3] : row2.dtypes
Out[3]: 
a      int64
b     uint64
c    float64
In[4] : a2 = row2.a.iloc[0]
In[5] : type(a2)
Out[5]: numpy.int64
In[6] : c2 = row2.c.iloc[0]
In[7] : type(c2)
Out[7]: numpy.float64

对我来说,这比两次转换数据类型(一次在行提取期间,一次之后)更为可取,并且比多次使用相同的行规范引用原始数据帧更为清晰(这在计算上可能非常昂贵)


我认为如果pandas有一个用于此操作的DataFrameRow类型会更好。

谢谢,但这两种类型都涉及复制/修改整个
数据框,对吗?仅仅获得一行就太过分了。是的,这是pandas在处理行时的限制。我也尝试过这样做,但这意味着你必须使用
.iloc[0]
单独提取每个值,也就是说,你失去了直接迭代行的能力。但似乎没有比这更好的内置方法了。我想我只需要编写自己的函数来构建相应的结构化数组。是的,这无助于对行进行迭代。我的目标是使用点符号从一行中访问各种值,因此这比
.iat
更清晰,即使使用
.iloc[0]
将事情弄得一团糟。
In[1] : row2 = df[2:2+1]
In[2] : type(row)
Out[2]: pandas.core.frame.DataFrame
In[3] : row2.dtypes
Out[3]: 
a      int64
b     uint64
c    float64
In[4] : a2 = row2.a.iloc[0]
In[5] : type(a2)
Out[5]: numpy.int64
In[6] : c2 = row2.c.iloc[0]
In[7] : type(c2)
Out[7]: numpy.float64