Python Pandas分层索引iterrows而不转换数据类型

时间:2015-04-18 03:04:11

标签: python pandas

我有一个带有分层索引的数据框。

In [57]: df = pd.DataFrame({('potential', 'sum'): {0: 8.0498308000000005, 1: 10901.381148799968}, ('datapoint_num', 'min'): {0: 1, 1: 6}, ('step_index', 'si'): {0: 1, 1: 6}, ('datapoint_num', 'N'): {0: 5, 1: 8600}, ('potential', 'sum_of_squares'): {0: 12.959955292916959, 1: 13910.219889184529}, ('datapoint_num', 'max'): {0: 5, 1: 8605}})

In [58]: df
Out[58]: 
   datapoint_num                potential                  step_index
               N   max  min           sum  sum_of_squares          si
0              5     5    1      8.049831       12.959955           1
1           8600  8605    6  10901.381149    13910.219889           6

我正在使用从流数据计算一堆摘要统计信息。我想迭代它的行,而不改变数据类型。其初始数据类型为:

In [43]: df.dtypes
step_index       si                  int64
datapoint_num    max                 int64
                 N                   int64
                 min                 int64
potential        sum_of_squares    float64
                 sum               float64
sn                                   int64

如果我打电话

for sn, row in df.iterrows:
    row.dtype

我看到pandas转换为一个系列,一切都变成了float64。 dif.iloc [0]似乎也预先形成了相同的类型转换。

使用

for i in df.index:
    row = df[df.sn == i]
    row.dtypes

我仍然有一个数据框,它似乎工作得很好(假设我的索引是唯一的),但我认为这样效率要低得多。

有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

您可以使用namedtuples和字典理解分配:

Row = namedtuple('Row', ['N', 'max', 'min', 'sum', 'sum_of_squares', 'si'])

rows = {i: Row(*df.iloc[i, :]) for i in df.index}

>>> rows
{0: Row(N=5.0, max=5.0, min=1.0, sum=8.0498308000000005, sum_of_squares=12.959955292916959, si=1.0),
 1: Row(N=8600.0, max=8605.0, min=6.0, sum=10901.381148799968, sum_of_squares=13910.219889184529, si=6.0)}

>>> type(rows[0].min)
numpy.float64

我注意到导入的数据类型也不是您所期望的,所以我不确定这将如何满足您的需求:

df = pd.DataFrame({('potential', 'sum'): {0: 8.0498308000000005, 1: 10901.381148799968}, ('datapoint_num', 'min'): {0: 1, 1: 6}, ('step_index', 'si'): {0: 1, 1: 6}, ('datapoint_num', 'N'): {0: 5, 1: 8600}, ('potential', 'sum_of_squares'): {0: 12.959955292916959, 1: 13910.219889184529}, ('datapoint_num', 'max'): {0: 5, 1: 8605}})

>>> df.iloc[0, 2]
1.0

>>> type(df.iloc[0, 2])
numpy.float64

你可能期待一个int64。

此外,因为这似乎是针对特定需求,所以它应该有效,因为子级别是唯一的(例如,只有'max')。更一般地说,可以通过level0:_level1创建链式密钥(例如,潜在的:_sum_of_squares)。

由于这些行现在是元组,因此无法更改数据(这可能是您想要的)。