Pandas 0.25.3的剪辑在某些情况下会在重新采样创建的块上崩溃。

问题描述 投票:4回答:1

在pandas 0.25.3中,我有一个关于基于时间的groupby结果的小问题。

我正在编写一个库来执行各种基于时间的聚合,并在非常特殊的情况下遇到了可能是一个bug。它在pandas>=1中没有发生,但如果可能的话,我希望仍然能够支持pandas 0.25.3(它在我们的用户中仍然是相关的)。

我缩小了以下案例的范围,结果在 "pandascoreinternalsblocks.py in where "中无限循环抓取异常,最终导致python崩溃,退出代码134。

import pandas as pd

data = pd.DataFrame(
    data=[15.0, 0.0, 0.0, -10.0,  0.0],
    index=pd.to_datetime(
        [
            "2018-01-01 00:00:00.000000",
            "2018-01-01 00:25:00.000000",
            "2018-01-01 00:30:00.000000",
            "2018-01-01 00:31:00.000000",
            "2018-01-01 00:47:00.000000",
        ]
    )
)


def clip_low_at_0(x):
    return x.clip(lower=0).sum()


data.resample("30min").agg(clip_low_at_0)

我的Python版本是3.7.6,pandas 0.25.3。

顺便说一下,它和迭代器一起工作得很好。

for entry, group in data.resample("30min"):
    clip_low_at_0(x=group)

迭代器:And data.groupby(pd.Grouper(freq="30min")) 有完全相同的问题。

引起问题的是这个组(第二个)。

                        0
2018-01-01 00:30:00   0.0
2018-01-01 00:31:00 -10.0
2018-01-01 00:47:00   0.0

就我检查的情况来看,似乎是这样的。

  • 只有特定数量的值,即2个值没有问题,3和4有一个问题,7没有。
  • 只有某些值的组合才会出现问题。这个会触发,有些不会,有些会。
  • 与任何指数值,似乎都没有关系。
  • 组的位置很重要

其实,通过进一步的挖掘,似乎导致错误的组生成的Series在 .clip() 被破坏了。试图 .copy() 它失败了,还有一些其他方法,比如序列化方法,都以错误结束。也许我没有正确使用group和agg,但是否有其他好的方法使用pandas来计算呢?

令我困扰的是,它似乎在很多情况下都能正常工作,而这种情况在pandas>=1.0.0中也能正常工作。

如果这是一个真正的bug,我当然会在问题中向pandas团队报告。(编辑:看来pandas并不鼓励在旧版本上报告bug)

编辑:为了澄清,我想......。

1)知道这到底是误用还是groupbyagg那边的实际bug。

2)如果有比自己做剪辑更好的变通方法(x.loc[x < 0] = 0)。因为这一组可能会导致将来其他用于聚合的函数出现其他问题。如果可能的话,我想保持重采样的方式不用自己处理索引,其实我做一些其他的聚合也是使用同样的结构。

python pandas debugging time-series pandas-groupby
1个回答
5
投票

我可以重现你的问题,但它似乎仅限于在使用 clip(),不是吗?其他功能如 round() 等似乎都能正常运行。所以这在我看来绝对是潘达斯的bug。

作为一个 通病 你可以直接使用 numpy 函数,而不是你的聚合函数中的潘达斯函数。

def clip_low_at_0(x):
    return numpy.clip(x, a_min=0, a_max=None).sum()

不过,为了完整起见: 具体的变通方法 (和a 诡异 的错误行为,也是一个)。clip() 就是明确设置一个上限。虽然我还没有对 何以 这个工作,实际上是这样的(至少在这里)。

def clip_low_at_0(x):
    # using numpy's 'double' dtype max value here, but this could
    # be replaced with sys.maxsize or any other sensible constant
    maxval = numpy.finfo('d').max
    return x.clip(lower=0, upper=maxval).sum()

最后(你已经知道了): 在聚合函数中不需要剪裁值, 你可以事先将它应用到整个DataFrame中。

data.clip(lower=0).resample("30min").sum()
© www.soinside.com 2019 - 2024. All rights reserved.