gpt4 book ai didi

python - Python numpy 中缺失值的奇怪计时

转载 作者:行者123 更新时间:2023-12-01 07:18:05 25 4
gpt4 key购买 nike

我有一个很长的一维 numpy 数组,其中有 10% 的缺失值。我想重复将其缺失值(np.nan)更改为其他值。我知道有两种方法可以做到这一点:

data[np.isnan(data)] = 0 或函数np.copyto(data, 0, where=np.isnan(data))

有时我想在那里放零,有时我想恢复nan。我认为重复重新计算 np.isnan 函数会很慢,最好保存 nan 的位置。下面代码的一些计时结果是违反直觉的。

我运行了以下命令:

import numpy as np
import sys
print(sys.version)
print(sys.version_info)
print(f'numpy version {np.__version__}')
data = np.random.random(100000)
data[data<0.1] = 0
data[data==0] = np.nan
%timeit missing = np.isnan(data)
%timeit wheremiss = np.where(np.isnan(data))
missing = np.isnan(data)
wheremiss = np.where(np.isnan(data))
print("Use missing list store 0")
%timeit data[missing] = 0
data[data==0] = np.nan
%timeit data[wheremiss] = 0
data[data==0] = np.nan
%timeit np.copyto(data, 0, where=missing)
print("Use isnan function store 0")
data[data==0] = np.nan
%timeit data[np.isnan(data)] = 0
data[data==0] = np.nan
%timeit np.copyto(data, 0, where=np.isnan(data))
print("Use missing list store np.nan")
data[data==0] = np.nan
%timeit data[missing] = np.nan
data[data==0] = np.nan
%timeit data[wheremiss] = np.nan
data[data==0] = np.nan
%timeit np.copyto(data, np.nan, where=missing)
print("Use isnan function store np.nan")
data[data==0] = np.nan
%timeit data[np.isnan(data)] = np.nan
data[data==0] = np.nan
%timeit np.copyto(data, np.nan, where=np.isnan(data))

我得到了以下输出(我冒昧地在时间线上添加了数字,以便我以后可以引用它们):

3.7.3 | packaged by conda-forge | (default, Jul  1 2019, 22:01:29) [MSC v.1900 64 bit (AMD64)]
sys.version_info(major=3, minor=7, micro=3, releaselevel='final', serial=0)
numpy version 1.17.1
01. 30 µs ± 2.68 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
02. 219 µs ± 24.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Use missing list store 0
03. 339 µs ± 23.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
04. 26 µs ± 1.92 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
05. 287 µs ± 26.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Use isnan function store 0
06. 38.5 µs ± 2.76 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
07. 43.8 µs ± 4.67 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Use missing list store np.nan
08. 328 µs ± 30.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
09. 24.8 µs ± 2.03 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
10. 322 µs ± 30 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Use isnan function store np.nan
11. 356 µs ± 31.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
12. 300 µs ± 4.29 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

这是第一个问题。为什么存储 np.nan 的时间比存储 0 的时间要长近 10 倍? (比较第 6 行和第 7 行与第 11 行和第 12 行)

与使用 isnan 函数重新计算缺失值相比,为什么使用存储的缺失列表需要更长的时间? (比较第 3 行和第 5 行与第 6 行和第 7 行)

这只是出于好奇。我可以看到最快的方法是使用 np.where 获取索引列表(因为我只缺少 10%)。但如果我有更多,事情可能不会那么明显。

最佳答案

因为你没有衡量你认为的自己!您在进行测试时会改变您的数据,并且timeit会多次运行测试。因此,在更改的数据上运行额外的运行。当您下次运行 isnan 时将值更改为 0 时,您什么也得不到,并且赋值基本上是无操作。而当您分配 nan 时,这会导致在下一次迭代中完成更多工作。

关于何时使用 np.where 与将其保留为 bool 数组的问题有点困难。它将涉及不同数据类型的相对大小(例如,bool 为 1 字节,int64 为 8 字节)、所选值的比例、分布匹配程度取决于 CPU/内存子系统的优化(例如,它们主要在一个 block 中还是均匀分布)、执行 np.where 的相对成本与结果将被重用的次数以及其他因素我现在想不起来。

对于其他用户,可能值得指出 RAM latency (i.e. speed) is >100 times slower than L1 cache ,因此保持内存访问的可预测性对于最大化缓存利用率非常重要

关于python - Python numpy 中缺失值的奇怪计时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57849285/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com