我想知道在pandas中是否有一种有效的方法:给定一个数据帧,第一行小于给定值是多少?例如,给定:
addr
0 4196656
1 4197034
2 4197075
3 4197082
4 4197134
Run Code Online (Sandbox Code Playgroud)
第一个小于4197080的值是多少?我想这回只是4197075.行A的解决办法是先通过过滤器和4197080然后坐最后一排,但是这看起来就像是一个极其缓慢的O(N)操作(第一建设一个数据帧,然后利用其最后一行),而二进制搜索将采用O(logN).
df.addr[ df.addr < 4197080].tail(1)
Run Code Online (Sandbox Code Playgroud)
我计时,并且创造df.addr[ df.addr < 4197080]或多或少的相同df.addr[ df.addr < 4197080].tail(1),强烈暗示内部它首先构建一个完整的df.
num = np.random.randint(0, 10**8, 10**6)
num.sort()
df = pd.DataFrame({'addr':num})
df = df.set_index('addr', drop=False)
df = df.sort_index()
Run Code Online (Sandbox Code Playgroud)
获得第一个较小的值非常慢:
%timeit df.addr[ df.addr < 57830391].tail(1)
100 loops, best of 3: 7.9 ms per loop
Run Code Online (Sandbox Code Playgroud)
使用lt改进了一点:
%timeit df.lt(57830391)[-1:]
1000 loops, best of 3: 853 µs per loop
Run Code Online (Sandbox Code Playgroud)
但仍远不及二元搜索那么快:
%timeit bisect(num, 57830391, 0, len(num))
100000 loops, best of 3: 6.53 µs per loop
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法?
这需要0.14.0
请注意,框架未排序.
In [16]: s = df['addr']
Run Code Online (Sandbox Code Playgroud)
找到低于要求的最大价值
In [18]: %timeit s[s<5783091]
100 loops, best of 3: 9.01 ms per loop
In [19]: %timeit s[s<5783091].nlargest(1)
100 loops, best of 3: 11 ms per loop
Run Code Online (Sandbox Code Playgroud)
所以这比实际执行完全排序然后索引更快.这.copy是为了避免偏向原地排序.
In [32]: x = np.random.randint(0, 10**8, 10**6)
In [33]: def f(x):
....: x.copy().sort()
....:
In [35]: %timeit f(x)
10 loops, best of 3: 67.2 ms per loop
Run Code Online (Sandbox Code Playgroud)
如果您只是搜索ALREADY SORTED系列,请使用searchsorted.请注意,您必须使用numpy版本(例如,操作.values.系列版本将在0.14.1中定义)
In [41]: %timeit s.values.searchsorted(5783091)
100000 loops, best of 3: 2.5 µs per loop
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2250 次 |
| 最近记录: |