当使用loc对 Dataframe 进行切片时,df.loc[start:end]包括开始和结束。在使用loc时,是否有简单的方法来排除结尾?
q35jwt9p1#
我能想到的最简单的是df.loc[start:end].iloc[:-1]。把最后一个砍掉。
df.loc[start:end].iloc[:-1]
6jjcrrmo2#
loc包括开始和结束,一个不太理想的解决方法是获取索引位置并使用iloc对 Dataframe 进行切片(假设您没有重复的索引):
loc
iloc
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
egmofgnx3#
没有一个答案解决end不是索引的一部分的情况。更通用的解决方案是简单地将索引与start和end进行比较,这样就可以强制它们中的任何一个是包含的或独占的。
end
start
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
7kqas0il4#
对于DatetimeIndex切片,可以尝试这样做。它会在你的结束时间前一纳秒内抓取所有内容。这将排除结束时间(假设您没有使用ns精度),但不一定是最后一次。
DatetimeIndex
df.loc[start:(end - pd.Timedelta('1ns'))]
pcrecxhr5#
pd.RangeIndex可以代替用于对索引进行切片,其中.loc具有独占停止 *,前提是 * 索引具有整数dtype。这里有一个简单的助手:
pd.RangeIndex
.loc
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:
range
print(df.loc[range(3, 5)])
vddsk6oq6#
似乎没有任何真正简洁的方法来做到这一点,但我更喜欢表达性的解决方案(我想做什么清楚吗?)).出于这个原因,我喜欢this solution,尽管它有点基础,有点笨拙。我认为,这个想法的一个更健壮、更有表现力、更高性能的版本是首先创建包含性切片,然后过滤结果以排除端点:
df.loc[start:end][lambda _: _.index != end]
这个解决方案相当快(我已经设置了s = start; e = end),并使用一个名为ts的系列来完成:
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]
ijnw1ujt7#
如果你正在使用另一个dataframe的索引中的datetime值。让我们假设你要使用的日期时间值是df1.index[0],你可以使用df1.index[0].resolution来获得该索引的分辨率。
end = df1.index[0] df.loc[:(end-end.resolution)]
7条答案
按热度按时间q35jwt9p1#
我能想到的最简单的是
df.loc[start:end].iloc[:-1]
。把最后一个砍掉。
6jjcrrmo2#
loc
包括开始和结束,一个不太理想的解决方法是获取索引位置并使用iloc
对 Dataframe 进行切片(假设您没有重复的索引):egmofgnx3#
没有一个答案解决
end
不是索引的一部分的情况。更通用的解决方案是简单地将索引与start
和end
进行比较,这样就可以强制它们中的任何一个是包含的或独占的。例如:
7kqas0il4#
对于
DatetimeIndex
切片,可以尝试这样做。它会在你的结束时间前一纳秒内抓取所有内容。这将排除结束时间(假设您没有使用ns精度),但不一定是最后一次。pcrecxhr5#
pd.RangeIndex
可以代替用于对索引进行切片,其中.loc
具有独占停止 *,前提是 * 索引具有整数dtype。这里有一个简单的助手:示例:
更简单的方法是使用python
range
:vddsk6oq6#
似乎没有任何真正简洁的方法来做到这一点,但我更喜欢表达性的解决方案(我想做什么清楚吗?)).
出于这个原因,我喜欢this solution,尽管它有点基础,有点笨拙。
我认为,这个想法的一个更健壮、更有表现力、更高性能的版本是首先创建包含性切片,然后过滤结果以排除端点:
这个解决方案相当快(我已经设置了
s = start; e = end
),并使用一个名为ts
的系列来完成:通过允许一个中间变量,可以使它更具可读性:
ijnw1ujt7#
如果你正在使用另一个dataframe的索引中的datetime值。让我们假设你要使用的日期时间值是df1.index[0],你可以使用df1.index[0].resolution来获得该索引的分辨率。