Pandas DataFrame列数据类型df.T.T!= df?

时间:2014-05-05 20:52:52

标签: python pandas

一般性问题,但我已经使用熊猫超过一年了,当我在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中的列没有一致的数据类型时,我应该注意什么?

2 个答案:

答案 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