在Pandas数据框中查找某个值的索引

6

我有一个问题,理论上不应该很难,但是却让我束手无策。肯定有一种简便的方法可以解决它。我有一个来自数据帧的序列,长这样:

               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,则必须再次迭代并测试更早的数字。肯定有一种不混乱的方法可以做到这一点,但我没有看到,可以避免所有这些逐步迭代。先感谢您的帮助。
2个回答

7

你实际上是在寻找两个条件。对于第一个条件,你希望给定的值大于0.1:

df['value'].gt(0.1)

对于第二个条件,你希望前一个非空值小于0.1:
df['value'].ffill().shift().lt(0.1)

现在,使用and运算符将这两个条件组合起来,反转结果布尔索引,并使用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来解决这个问题。


简单而优雅。谢谢! - Windstorm1981
很棒的答案。Idmax 部分非常聪明。 - anniejcannon

4

记账

# 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(stackoverflow)动态。我们回答问题时通常通过编辑我们的问题直到它们满足要求。我注意到,那些回答pandas问题的人通常相互之间很有帮助,也对那些提问的人很有帮助。

在这篇文章中,我被 @root 很好地启示,随后修改了我的文章以反映出新增的信息。仅此一点就使@root的帖子非常有用,除非还包含其他优秀的信息。

请认可两篇帖子并尽可能多地点赞有用的帖子。

谢谢


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接