一般性问题,但我已经使用熊猫超过一年了,当我在pandas DataFrame列中混合类型时,我一直遇到麻烦。我经常会有一个像这样的DataFrame:
df2 =
0 1 2 3 4
val_str test test test test test
val_date 2014-01-15 2014-01-15 2014-01-15 2014-01-15 2014-01-15
val_float 1.5 1.5 1.5 1.5 1.5
val_int 1 1 1 1 1
作为示例生成:
import pandas as pd
import datetime
df = pd.DataFrame(index=range(5))
df['val_str'] = "test"
df['val_date']= datetime.datetime(2014,1,15)
df['val_bool'] = True
df['val_float'] = 1.5
df['val_int'] = 1
df2=df.T
令人费解的例子,但数据来自excel,csv等,而且很多时候行具有一致的数据类型而不是列。
Pandas似乎(大多数情况下)使用这种数据来处理它的方法,但在选择或尝试对数据进行布尔运算时,我经常得到意想不到的结果。
使用例如
选择数据df2[2]['val_bool'] #eems to work without problem
似乎运作良好,甚至用例如:
拉出行df2.ix['val_bool'] # works fine
似乎按预期工作。尝试使用此切片进一步选择数据时,我经常遇到问题。
df2.ix['val_bool'].dtype
>>> dtype('O')
# trying boolean operations on this gives numeric results?
是否有任何大熊猫指南可能会导致问题。我已经回到一些初始教程并收集了列“应该”具有一致的数据类型。然而,熊猫的灵活性允许你这样做,但有些方法会破坏吗?我依稀记得Wes McKinneys的一个讲话,他提到了:
df.T.T != df
有什么区别,当DataFrame中的列没有一致的数据类型时,我应该注意什么?
答案 0 :(得分:5)
数据类型是基于列的。在混合类型框架中执行转置df.T
,必然会转换为可以包含两种类型的类型,这意味着字符串和float将产生object
dtype。
所以df.T.T != df
,但是,你可以这样做:df.T.T.convert_objects()
通常会成功将object
dtypes转换回基本类型。
答案 1 :(得分:5)
在引擎盖下,Pandas在Block中存储具有相同dtype的列或列组。因此,您可以将所有浮点列存储在一个大数组中,将所有字符串列存储在另一个数组中,等等。
如果您有异质列数据,例如上面的df2
,则每个值都存储在dtype object
数组中:
In [154]: df2._data
Out[154]:
BlockManager
Items: Int64Index([0, 1, 2, 3, 4], dtype='int64')
Axis 1: Index([u'val_str', u'val_date', u'val_bool', u'val_float', u'val_int'], dtype='object')
ObjectBlock: [0, 1, 2, 3, 4], 5 x 5, dtype: object
这是最糟糕的dtype,因为它没有NumPy数字类型提供的速度优势。此外,一些NumPy(可能还有Pandas)函数在对象dtype数组上运行时会引发异常。
即使选择只有浮点值的行,也会返回一个对象dtype数组:
In [149]: df2.loc['val_float'].dtype
Out[149]: dtype('O')
因此,利用pandas的最佳方法是以允许整列具有除object
之外的NumPy dtypes的方式加载数据,并且永远不会转置(除非整个DataFrame是同类dtype)。
注意df
的列如何分隔成不同dtype的块。这比df2
的一个大ObjectBlock
要好得多。
In [155]: df._data
Out[155]:
BlockManager
Items: Index([u'val_str', u'val_date', u'val_bool', u'val_float', u'val_int'], dtype='object')
Axis 1: Int64Index([0, 1, 2, 3, 4], dtype='int64')
ObjectBlock: [val_str], 1 x 5, dtype: object
DatetimeBlock: [val_date], 1 x 5, dtype: datetime64[ns]
BoolBlock: [val_bool], 1 x 5, dtype: bool
FloatBlock: [val_float], 1 x 5, dtype: float64
IntBlock: [val_int], 1 x 5, dtype: int64