【发布时间】:2018-11-11 00:51:37
【问题描述】:
有些日子我只是讨厌使用中间件。以这个为例:我想要一个查找表,将一组输入(域)值中的值映射到输出(范围)值。映射是唯一的。 Python 地图可以做到这一点,但由于我认为地图很大,为什么不使用 ps.Series 及其索引,这增加了我可以做到的好处:
- 传入多个值以作为一个系列进行映射(希望比字典查找更快)
- 结果中保留了原始系列的索引
像这样:
domain2range = pd.Series(allrangevals, index=alldomainvals)
# Apply the map
query_vals = pd.Series(domainvals, index=someindex)
result = query_vals.map(domain2range)
assert result.index is someindex # Nice
assert (result.values in allrangevals).all() # Nice
按预期工作。但不是。上面的 .map 的时间成本随着 len(domain2range) 而不是(更明智地)O(len(query_vals)) 增加,如图所示:
numiter = 100
for n in [10, 1000, 1000000, 10000000,]:
domain = np.arange(0, n)
range = domain+10
maptable = pd.Series(range, index=domain).sort_index()
query_vals = pd.Series([1,2,3])
def f():
query_vals.map(maptable)
print n, timeit.timeit(stmt=f, number=numiter)/numiter
10 0.000630810260773
1000 0.000978469848633
1000000 0.00130645036697
10000000 0.0162791204453
捂脸。在 n=10000000 时,每个映射值需要 (0.01/3) 秒。
所以,问题:
- Series.map 是否应该表现得像这样?为什么它如此彻底,可笑的慢?我认为我正在使用它,如文档中所示。
- 有没有一种使用 pandas 进行表查找的快速方法。好像不是上面的吗?
【问题讨论】:
-
@TemporalWolf 我要说的是,如果每个查询值需要 (1.44/3) 秒,那么它不会针对任何事情进行优化。
-
以上代码可运行并提供数据。映射表从 0..n ==> 10..n+10 映射值,查询始终为 [1,2,3]。
-
您确实意识到将
number=10传递给timeit正在测量执行10 次的时间,对吧? -
好的。除以 10。还是不合理
-
我已经用正确的时间更新了这个问题。仍然非常非常慢。