我有一個長的 1-d numpy 數組,其中有 10% 的缺失值。我想反復將其缺失值(np.nan)更改為其他值。我知道有兩種方法可以做到這一點:data[np.isnan(data)] = 0或功能 np.copyto(data, 0, where=np.isnan(data))有時我想把零放在那里,其他時候我想恢復nans. 我認為np.isnan重復重新計算函數會很慢,最好保存nans的位置。下面代碼的一些計時結果是違反直覺的。我運行了以下內容:import numpy as npimport sysprint(sys.version)print(sys.version_info)print(f'numpy version {np.__version__}')data = np.random.random(100000)data[data<0.1] = 0data[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] = 0data[data==0] = np.nan%timeit data[wheremiss] = 0data[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)] = 0data[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.nandata[data==0] = np.nan%timeit data[wheremiss] = np.nandata[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.nandata[data==0] = np.nan%timeit np.copyto(data, np.nan, where=np.isnan(data))所以這是第一個問題。為什么存儲 a 的時間np.nan比存儲 0 的時間要長近 10 倍?(比較第 6 行和第 7 行與第 11 行和第 12 行)missing與使用函數重新計算缺失值相比,為什么使用存儲的列表需要更長的時間isnan?(比較第 3 行和第 5 行與第 6 行和第 7 行)這只是出于好奇。我可以看到最快的方法是使用np.where獲取索引列表(因為我只有 10% 丟失)。但如果我有更多,事情可能不會那么明顯。
1 回答

LEATH
TA貢獻1936條經驗 獲得超7個贊
因為你沒有衡量你認為你是什么!您data
在進行測試時正在改變您的,并timeit
多次運行測試。因此,額外的運行正在更改的數據上運行。當您將值更改為0
下一次運行時,isnan
您將一無所獲,并且分配基本上是無操作的。而當您分配nan
它時,會導致在下一次迭代中完成更多工作。
您關于何時使用np.where
與將其保留為 s 數組的問題bool
有點困難。它將涉及不同數據類型的相對大?。ɡ?code>bool1 字節、int64
8 字節)、選擇的值的比例、分布與 CPU/內存子系統優化的匹配程度(例如,它們主要在一個塊中)與均勻分布),做的相對成本np.where
與結果將被重用的次數,以及其他我現在想不到的事情。
對于其他用戶,可能值得指出的是RAM 延遲(即速度)比 L1 緩存慢 100 倍以上,因此保持內存訪問可預測對于最大化緩存利用率很重要
添加回答
舉報
0/150
提交
取消