在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
就我检查的情况来看,似乎是这样的。
其实,通过进一步的挖掘,似乎导致错误的组生成的Series在 .clip()
被破坏了。试图 .copy()
它失败了,还有一些其他方法,比如序列化方法,都以错误结束。也许我没有正确使用group和agg,但是否有其他好的方法使用pandas来计算呢?
令我困扰的是,它似乎在很多情况下都能正常工作,而这种情况在pandas>=1.0.0中也能正常工作。
如果这是一个真正的bug,我当然会在问题中向pandas团队报告。(编辑:看来pandas并不鼓励在旧版本上报告bug)
编辑:为了澄清,我想......。
1)知道这到底是误用还是groupbyagg那边的实际bug。
2)如果有比自己做剪辑更好的变通方法(x.loc[x < 0] = 0)。因为这一组可能会导致将来其他用于聚合的函数出现其他问题。如果可能的话,我想保持重采样的方式不用自己处理索引,其实我做一些其他的聚合也是使用同样的结构。
我可以重现你的问题,但它似乎仅限于在使用 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()