我遇到了一个不应该那么困难的问题,但它让我感到难过。必须有一个简单的方法来做到这一点。我有一个来自数据框的系列,如下所示:
value
2001-01-04 0.134
2001-01-05 Nan
2001-01-06 Nan
2001-01-07 0.032
2001-01-08 Nan
2001-01-09 0.113
2001-01-10 Nan
2001-01-11 Nan
2001-01-12 0.112
2001-01-13 Nan
2001-01-14 Nan
2001-01-15 0.136
2001-01-16 Nan
2001-01-17 Nan
从下到上迭代,我需要在下一个最早日期小于0.100的最早日期找到大于0.100的值的索引。
所以在上面的系列中,我想找到值为0.113的索引,即2001-01-09。下一个早期值低于0.100(2001-01-07为0.031)。后两个值大于0.100,但我想要最早值的索引> 0.100跟随小于阈值的值从下到上迭代。
我能想到这样做的唯一方法是反转系列,迭代到第一个(最后一个)值,检查它是否是> 0.100,然后再次迭代到下一个早期值,并检查它是否小于0.100。如果我没有完成。如果它> 0.100我必须再次迭代并测试前面的数字。
当然,有一种非混乱的方法可以做到这一点我没有看到避免所有这种逐步迭代。
先谢谢你的帮助。
答案 0 :(得分:7)
你基本上是在寻找两个条件。对于第一个条件,您希望给定值大于0.1:
df['value'].gt(0.1)
对于第二个条件,您希望先前的非空值小于0.1:
df['value'].ffill().shift().lt(0.1)
现在,将两个条件与运算符结合使用,反转生成的布尔索引器,并使用idxmax
查找条件所在的第一个(最后一个)实例:
(df['value'].gt(0.1) & df['value'].ffill().shift().lt(0.1))[::-1].idxmax()
它给出了预期的指数值。
上述方法假设至少有一个值满足您所描述的情况。如果您的数据可能无法满足您的情况,则可能需要使用any
来验证解决方案是否存在:
# Build the condition.
cond = (df['value'].gt(0.1) & df['value'].ffill().shift().lt(0.1))[::-1]
# Check if the condition is met anywhere.
if cond.any():
idx = cond.idxmax()
else:
idx = ???
在你的问题中,你已经指出两个不等式都是严格的。如果一个值恰好等于0.1,会发生什么?您可能需要将gt
/ lt
中的一个更改为ge
/ le
以解决此问题。
答案 1 :(得分:4)
<强> Bookkeepping 强>
# making sure `nan` are actually `nan`
df.value = pd.to_numeric(df.value, 'coerce')
# making sure strings are actually dates
df.index = pd.to_datetime(df.index)
计划
dropna
sort_index
0.1
diff
diff
- 当我们从< .1
转到> .1
时,您的方案就会发生。在这种情况下,diff
将为-1
idxmax
- 找到第一个-1
df.value.dropna().sort_index().lt(.1).astype(int).diff().eq(-1).idxmax()
2001-01-09 00:00:00
更正确定了@root指出的缺陷。
diffs = df.value.dropna().sort_index().lt(.1).astype(int).diff().eq(-1)
diffs.idxmax() if diffs.any() else pd.NaT
社论
这个问题突出了一个重要的SO动态。我们回答问题通常是通过编辑我们的问题直到他们处于令人满意的状态。我观察到,我们这些回答pandas
个问题的人通常对提出问题的人都非常有帮助。
在这篇文章中,我很了解@root并随后更改了我的帖子以反映添加的信息。除了他们提供的其他重要信息之外,仅此一点使@ root的帖子非常有用。
请尽可能多地识别帖子和向上投票。
THX