Python 如果数据帧中存在上一个和下一个索引值,则获取它们

Python 如果数据帧中存在上一个和下一个索引值,则获取它们,python,pandas,dataframe,Python,Pandas,Dataframe,假设我有一个数据帧 df = pd.DataFrame(dict(vals=np.random.randint(0, 10, 10)), index=pd.date_range('20170401', '20170410')) >>> df vals 2017-04-01 9 2017-04-02 8 2017-04-03 4 2017-04-04 5 2017-04-05

假设我有一个数据帧

df = pd.DataFrame(dict(vals=np.random.randint(0, 10, 10)),
                  index=pd.date_range('20170401', '20170410'))

>>> df
               vals
2017-04-01     9
2017-04-02     8
2017-04-03     4
2017-04-04     5
2017-04-05     9
2017-04-06     9
2017-04-07     5
2017-04-08     3
2017-04-09     3
2017-04-10     1
我知道某个日期在我的索引中,但不知道它的位置,例如

cur_dt = df.index[np.random.randint(0, df.index.size)]

>>> cur_dt
Timestamp('2017-04-05 00:00:00', freq='D')
给定
cur_dt
,我想确定索引中的上一个和下一个值是什么。如果
cur_dt
是我索引中的第一个(最后一个)值,那么上一个(下一个)元素应该是
cur_dt
本身

总而言之,我的问题是,,在给定当前值的情况下,查找索引中上一个和下一个值(或当前值本身,如果它是端点)的最简单方法是什么


我目前的做法似乎有些迂回,这就是我提出问题的动机

cur_iloc = df.index.get_loc(cur_dt)
prev = cur_dt if cur_iloc == 0 else df.index[cur_iloc-1]
next = cur_dt if cur_iloc == df.index.size-1 else df.index[cur_iloc+1]

>>> prev
Timestamp('2017-04-04 00:00:00', freq='D')
>>> next
Timestamp('2017-04-06 00:00:00', freq='D')

如果没有更直截了当的方法,那么我道歉。我想象着能够将我的索引从当前值向前和向后“移动”一次(对端点进行一些很好的处理),但不确定这是否可行

假设索引已排序,请尝试使用:

源数据集:

In [185]: df
Out[185]:
            vals
2017-04-01     5
2017-04-02     3
2017-04-03     9
2017-04-04     8
2017-04-05     1
2017-04-06     0
2017-04-07     4
2017-04-08     5
2017-04-09     1
2017-04-10     8

In [186]: cur_dt
Out[186]: Timestamp('2017-04-02 00:00:00', freq='D')
In [187]: idx = np.searchsorted(df.index, cur_dt)

In [188]: df.index[max(0, idx-1)]
Out[188]: Timestamp('2017-04-01 00:00:00', freq='D')

In [189]: df.index[min(idx+1, len(df)-1)]
Out[189]: Timestamp('2017-04-03 00:00:00', freq='D')
解决方案:

In [185]: df
Out[185]:
            vals
2017-04-01     5
2017-04-02     3
2017-04-03     9
2017-04-04     8
2017-04-05     1
2017-04-06     0
2017-04-07     4
2017-04-08     5
2017-04-09     1
2017-04-10     8

In [186]: cur_dt
Out[186]: Timestamp('2017-04-02 00:00:00', freq='D')
In [187]: idx = np.searchsorted(df.index, cur_dt)

In [188]: df.index[max(0, idx-1)]
Out[188]: Timestamp('2017-04-01 00:00:00', freq='D')

In [189]: df.index[min(idx+1, len(df)-1)]
Out[189]: Timestamp('2017-04-03 00:00:00', freq='D')

重置索引,然后使用布尔逻辑识别
cur\u dt
的位置,如下所示:

df = df.reset_index()
cur_dt_index = df.index[np.random.randint(0, df['index'].size)]
previous = max(cur_dt_index-1, 0)
next = min(cur_dt_index + 1, df.shape[0])

创建一个新的timeseries ts,其索引与df相同,df将存储以前的索引(并确保ts的索引已排序),然后简单地将ts移位1

ts=pd.Series(df.index,index=df.index).sort_index().shift(1)

(如果只需查找上一个索引一次,则速度可能会较慢,但如果需要多次查找,则速度会更快。)

Ah这是一种改进,肯定会更清晰、更短。谢谢你,麦克斯!也许有一个问题:是否有什么特别的原因让我更喜欢
np.searchsorted
而不是
df.index.get_loc
?@Erickhansen,
df.index.get_loc
-可能比
np.searchsorted
更快(或更快)。我认为最好的方法是根据您的数据进行测试;-)这是公平的。还有一根骨头要挑;)我想应该是
len(df)-1
,不是吗?@erickhansen,是的,很好,谢谢!我在回答中已经改正了