python Pandas切片不包括结束

iyfamqjs  于 2023-06-04  发布在  Python
关注(0)|答案(7)|浏览(348)

当使用loc对 Dataframe 进行切片时,
df.loc[start:end]
包括开始和结束。在使用loc时,是否有简单的方法来排除结尾?

q35jwt9p

q35jwt9p1#

我能想到的最简单的是df.loc[start:end].iloc[:-1]
把最后一个砍掉。

6jjcrrmo

6jjcrrmo2#

loc包括开始和结束,一个不太理想的解决方法是获取索引位置并使用iloc对 Dataframe 进行切片(假设您没有重复的索引):

df=pd.DataFrame({'A':[1,2,3,4]}, index = ['a','b','c','d'])

df.iloc[df.index.get_loc('a'):df.index.get_loc('c')]

#   A
#a  1
#b  2

df.loc['a':'c']

#   A
#a  1
#b  2
#c  3
egmofgnx

egmofgnx3#

没有一个答案解决end不是索引的一部分的情况。更通用的解决方案是简单地将索引与startend进行比较,这样就可以强制它们中的任何一个是包含的或独占的。

df[(df.index >= start) & (df.index < end)]

例如:

>>> import pandas as pd
>>> import numpy as np

>>> df = pd.DataFrame(
    {
        "x": np.arange(48),
        "y": np.arange(48) * 2,
    },
    index=pd.date_range("2020-01-01 00:00:00", freq="1H", periods=48)
)

>>> start = "2020-01-01 14:00"
>>> end = "2020-01-01 19:30" # this is not in the index

>>> df[(df.index >= start) & (df.index < end)]

                    x   y
2020-01-01 14:00:00 14  28
2020-01-01 15:00:00 15  30
2020-01-01 16:00:00 16  32
2020-01-01 17:00:00 17  34
2020-01-01 18:00:00 18  36
2020-01-01 19:00:00 19  38
7kqas0il

7kqas0il4#

对于DatetimeIndex切片,可以尝试这样做。它会在你的结束时间前一纳秒内抓取所有内容。这将排除结束时间(假设您没有使用ns精度),但不一定是最后一次。

df.loc[start:(end - pd.Timedelta('1ns'))]
pcrecxhr

pcrecxhr5#

pd.RangeIndex可以代替用于对索引进行切片,其中.loc具有独占停止 *,前提是 * 索引具有整数dtype。这里有一个简单的助手:

class _eidx:
    def __getitem__(self, s: slice) -> pd.RangeIndex:
        return pd.RangeIndex(s.start, s.stop, s.step)
eidx = _eidx()

示例:

df = pd.DataFrame({"x": range(10), "y": range(10, 20)})

print(df.loc[eidx[3:5]])
x   y
3  3  13
4  4  14

更简单的方法是使用python range

print(df.loc[range(3, 5)])
x   y
3  3  13
4  4  14
vddsk6oq

vddsk6oq6#

似乎没有任何真正简洁的方法来做到这一点,但我更喜欢表达性的解决方案(我想做什么清楚吗?)).
出于这个原因,我喜欢this solution,尽管它有点基础,有点笨拙。
我认为,这个想法的一个更健壮、更有表现力、更高性能的版本是首先创建包含性切片,然后过滤结果以排除端点:

df.loc[start:end][lambda _: _.index != end]

这个解决方案相当快(我已经设置了s = start; e = end),并使用一个名为ts的系列来完成:

In [1]: %timeit ts[s:e]
135 µs ± 1.07 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [2]: %timeit ts[(ts.index >= s) & (ts.index < e)]
45.1 ms ± 142 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [3]: %timeit ts[s:e][lambda s: s.index != e]
299 µs ± 1.75 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

通过允许一个中间变量,可以使它更具可读性:

inclusive = df.loc[start:end]
exclusive = inclusive[inclusive.index != end]
ijnw1ujt

ijnw1ujt7#

如果你正在使用另一个dataframe的索引中的datetime值。让我们假设你要使用的日期时间值是df1.index[0],你可以使用df1.index[0].resolution来获得该索引的分辨率。

end = df1.index[0]
df.loc[:(end-end.resolution)]

相关问题