python - 查找 Pandas 索引列值对的最快方法
问题描述
我有一个较大的 DataFrame,其中包含日期索引 ['Date'] 和几列。一列是字符串标识符 ['Type'],其余列中包含相关数据。我需要将 newData 添加到 DataFrame,但前提是 DataFrame 中不存在日期类型对(即 index-ColumnValue 对)。检查现有配对占用了我大约 95% 的代码计算时间,所以我真的需要找到一种更快的方法来完成它。
已考虑的选项,时间按速度递增的顺序排列::
existing_pair = len(compiledData[(compiledData['Type'] == newData['Type'])
& (compiledData.index == newData['Date'])]) > 0
# average = 114 ms
existing_pair = newData['Date'] in compiledData[compiledData['Type'] ==
newData['Type']].index
# average = 68 ms
existing_pair = compiledData[compiledData.index == newData['Type']]['Type'].
isin([newData['Date']]).any()
# average = 44 ms
我对 Python 比较陌生,所以我确信有更好(= 更快)的方法来检查 index-colVal 对。或者,可能是我的整个数据结构错了。任何人都可以提供任何指示,将不胜感激。
编辑:compiledData 数据框的示例:
Type ColA ColB ColC ColD ColE ColF
2021-01-19 B 83.0 -122.15 0.0 11.0 11.000 11.0
2021-01-19 D 83.0 -1495.48 0.0 11.0 11.000 11.0
2021-03-25 D 83.0 432.00 0.0 11.0 11.000 11.0
2021-04-14 D 83.0 646.00 0.0 11.0 11.000 11.0
2021-04-16 A 20.0 11.00 0.0 30.0 11.000 11.0
2021-04-25 D 83.0 -26.82 0.0 11.0 11.000 11.0
2021-04-28 B 83.0 -651.00 0.0 11.0 11.000 11.0
解决方案
索引值查找比列值查找更快。我不知道实现细节(看起来查找取决于行数)。这是性能比较:
def test_value_matches(df, v1, v2):
# return True if v1, v2 found in df columns, else return False
if any(df[(df.c1 == v1) & (df.c2 == v2)]):
return True
return False
def test_index_matches(df, v1, v2):
# returns True if (v1, v2) found in (multi) index, else returns False
if (v1, v2) in df.index:
return True
return False
# test dependence of funcs above on num rows in df:
for n in [int(j) for j in [1e4, 1e5, 1e6, 1e7]]:
df = pd.DataFrame(np.random.random(size=(n, 2)), columns=["c1", "c2"])
v1, v2 = df.sample(n=1).iloc[0]
%timeit test_value_matches(df, v1, v2)
# create an index based on column values:
df2 = df.set_index(["c1", "c2"])
%timeit test_index_matches(df2, v1, v2)
输出
421 µs ± 22.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
10.5 µs ± 175 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
557 µs ± 5.35 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
10.3 µs ± 143 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
3.77 ms ± 166 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
16.5 µs ± 185 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
22.4 ms ± 2.06 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
28.1 µs ± 10.2 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
请注意,这忽略了索引时间本身,这可能很重要;这种方法可能最适合在同一个 df 上重复查找。因为n=1e7
,性能就像你在我的机器上的问题;索引版本的速度要快约 1000 倍(尽管显然随着 增长n
)。
推荐阅读
- excel - 数组不打印到我的第二个工作表的第二行?
- regex - 匹配多行正则表达式以 if 开头并以以右花括号开头的行结尾
- laravel - Laravel forgen 密钥未通过测试
- python-3.x - 如何使用python3获取每日数据报告
- jquery - 使用 jquery 访问设置为 attr 的 Mongoose 模式键(布尔值),但它返回未定义
- laravel - 在 Laravel 中克隆一组数据
- python - python web-scraping ==> 谷歌搜索
- reactjs - 测试无法读取 null 的属性 InnerHTML
- java - 使用凭据对用户进行身份验证
- linux - yum 依赖解析在 docker build 与 docker run 中的行为不同