【Numpy核心編程攻略:Python數據處理、分析詳解與科學計算】2.1 NumPy高級索引:布爾型與花式索引的底層原理

在這里插入圖片描述

2.1 NumPy高級索引:布爾型與花式索引的底層原理

目錄
NumPy高級索引:布爾型與花式索引的底層原理
布爾索引
花式索引
索引優化技巧
NumPy索引體系
基本索引
高級索引
布爾索引
花式索引
掩碼機制
元素篩選
整數數組
多維索引
內存拷貝
內存重組
文章內容

NumPy 是 Python 中非常重要的數值計算庫,提供了高效的數組操作功能。在 NumPy 中,高級索引(Advanced Indexing)是處理數組時非常強大的工具。本文將詳細探討布爾索引和花式索引的底層原理,包括數組掩碼機制、內存布局原理、索引優化技巧等方面。通過本文的學習,讀者將能夠更好地理解 NumPy 的高級索引機制,并在實際應用中更加高效地使用這些功能。

布爾索引

2.1.1 布爾索引原理

布爾索引允許我們使用布爾數組來選擇數組中的元素。布爾數組的每個元素都是一個布爾值(True 或 False),布爾數組的形狀必須與被索引的數組的形狀一致。NumPy 會根據布爾數組中的 True 位置返回相應的元素。

原理說明
  • 布爾數組的生成:布爾數組通常通過條件操作生成。例如,我們可以使用 ><== 等比較運算符來生成布爾數組。
  • 布爾索引的執行:當使用布爾數組進行索引時,NumPy 會遍歷布爾數組,找到所有值為 True 的位置,并返回這些位置對應的元素。
示例代碼
import numpy as np# 創建一個 NumPy 數組
arr = np.array([1, 2, 3, 4, 5])
# 生成布爾數組
mask = arr > 3  # [False, False, False, True, True]
# 使用布爾數組進行索引
result = arr[mask]  # [4, 5]
print(result)  # 輸出 [4 5]
2.1.2 數組掩碼機制

在布爾索引中,布爾數組實際上起到了掩碼(Mask)的作用。掩碼是一種常見的數據處理技術,用于選擇或過濾數據。NumPy 的布爾索引通過布爾數組來實現掩碼機制。
布爾索引本質是元素級選擇操作,其數學表達式為:

result = { x i ∣ m i = True , i ∈ [ 0 , n ) } \text{result} = \{ x_i \mid m_i = \text{True}, i \in [0,n) \} result={xi?mi?=True,i[0,n)}

其中 m m m是布爾掩碼數組, x x x是原始數組。NumPy底層通過C語言的npy_bool類型實現高效掩碼運算。

內存示意圖:

原始數組
布爾掩碼
掩碼運算
結果數組
選中的元素
NumPy 數組
布爾數組
被選中的元素
未被選中的元素
輸出數組
被忽略
原始內存布局
掩碼內存布局
代碼示例
# 創建一個 NumPy 數組
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 生成布爾數組
mask = arr > 5  # [[False, False, False], [False, True, True], [True, True, True]]
# 使用布爾數組進行索引
result = arr[mask]
print(result)  # 輸出 [6 7 8 9]
2.1.3 布爾索引與視圖關系

布爾索引返回的是一個新的數組,而不是視圖。這意味著使用布爾索引選擇的數據會被復制到一個新的內存區域中,而不是在原數組上進行操作。這一點與基本索引不同,基本索引返回的是原數組的一個視圖。

示例代碼
# 創建一個 NumPy 數組
arr = np.array([1, 2, 3, 4, 5])
# 生成布爾數組
mask = arr > 3  # [False, False, False, True, True]
# 使用布爾數組進行索引
result = arr[mask]
# 修改原數組
arr[0] = 10
# 檢查結果數組是否改變
print(result)  # 輸出 [4 5]

花式索引

2.1.4 花式索引原理

花式索引(Fancy Indexing)允許我們使用一個整數數組來選擇元素。整數數組中的每個元素是一個索引值,NumPy 會根據這些索引值返回相應的元素。花式索引可以用于多維數組,通過傳入多個整數數組來選擇特定的子數組。

原理說明
  • 整數數組的生成:整數數組可以是手動創建的,也可以通過其他數組操作生成。
  • 花式索引的執行:當使用整數數組進行索引時,NumPy 會遍歷整數數組,找到所有索引值,并返回這些索引值對應的元素。
    花式索引使用整數數組指定元素位置,其內存訪問模式為:
indices = [1, 3, 5]
result = arr[indices]  # 非連續內存訪問

內存布局示意圖:

原始內存
索引0
索引1
索引5
新數組位置0
新數組位置1
新數組位置2

性能測試代碼:

# 創建大型數組測試訪問性能
arr = np.random.rand(1000000)
indices = np.random.randint(0, 1000000, 500000)# 連續索引(基礎索引)
%timeit arr[100:200]       # 約150ns(利用內存連續性)# 非連續索引(花式索引)
%timeit arr[indices]       # 約2.5ms(隨機內存訪問)

示例代碼
# 創建一個 NumPy 數組
arr = np.array([1, 2, 3, 4, 5])
# 生成整數數組
indices = np.array([1, 3, 4])
# 使用整數數組進行索引
result = arr[indices]
print(result)  # 輸出 [2 4 5]
2.1.5 內存布局原理

花式索引返回的是一個新的數組,而不是視圖。這意味著使用花式索引選擇的數據會被復制到一個新的內存區域中。NumPy 通過內部的 C 擴展來實現這一過程,具體包括內存分配、數據復制等步驟。

內存示意圖
NumPy 數組
整數數組
被選中的元素
未被選中的元素
輸出數組
被忽略
原始內存布局
索引內存布局
代碼示例
# 創建一個 NumPy 數組
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 生成整數數組
row_indices = np.array([0, 2])
col_indices = np.array([1, 2])
# 使用花式索引
result = arr[row_indices, col_indices]
print(result)  # 輸出 [2 9]

索引優化技巧

2.1.6 布爾索引優化

布爾索引的優化主要集中在減少不必要的復制操作和提高條件判斷的效率上。

優化技巧
  • 使用 np.wherenp.where 函數可以高效地生成布爾索引的結果,避免直接生成布爾數組。
  • 避免多次索引:盡量避免對同一個數組進行多次布爾索引操作,可以將多次操作合并為一次。
示例代碼
# 創建一個 NumPy 數組
arr = np.array([1, 2, 3, 4, 5])
# 使用 np.where 進行布爾索引
result = arr[np.where(arr > 3)]
print(result)  # 輸出 [4 5]
2.1.7 花式索引優化

花式索引的優化主要集中在減少內存分配和提高索引操作的效率上。

優化技巧
  • 使用 np.takenp.take 函數可以高效地從數組中選擇特定的索引,避免復雜的索引操作。
  • 避免多次索引:盡量避免對同一個數組進行多次花式索引操作,可以將多次操作合并為一次。
示例代碼
# 創建一個 NumPy 數組
arr = np.array([1, 2, 3, 4, 5])
# 生成整數數組
indices = np.array([1, 3, 4])
# 使用 np.take 進行花式索引
result = np.take(arr, indices)
print(result)  # 輸出 [2 4 5]

性能對比測試

2.1.8 布爾索引與花式索引的性能對比

為了更好地理解布爾索引和花式索引的性能差異,我們可以進行一些簡單的性能測試。

測試代碼
import time# 創建一個大型 NumPy 數組
arr = np.random.randint(0, 100, size=1000000)# 測試布爾索引
start_time = time.time()
mask = arr > 50
result_bool = arr[mask]
end_time = time.time()
time_bool = end_time - start_time# 測試花式索引
start_time = time.time()
indices = np.where(arr > 50)[0]
result_fancy = np.take(arr, indices)
end_time = time.time()
time_fancy = end_time - start_timeprint(f"布爾索引耗時: {time_bool:.6f} 秒")
print(f"花式索引耗時: {time_fancy:.6f} 秒")

數據篩選性能測試

方法10^6元素耗時內存占用
布爾索引2.1ms8MB
花式索引3.8ms8MB
where()2.3ms16MB

實際應用場景對比

2.1.9 布爾索引的實際應用

布爾索引在數據過濾和條件選擇中非常有用。例如,我們可以使用布爾索引來選擇某個條件下的所有數據。

示例代碼
# 創建一個 NumPy 數組
data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 選擇所有大于 5 的元素
filtered_data = data[data > 5]
print(filtered_data)  # 輸出 [6 7 8 9]
2.1.10 花式索引的實際應用

花式索引在多維數組中選擇特定的子數組時非常有用。例如,我們可以使用花式索引來選擇某個特定的行和列。

示例代碼
# 創建一個 NumPy 數組
data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 選擇第 0 行和第 2 行的第 1 列和第 2 列
selected_data = data[[0, 2], [1, 2]]
print(selected_data)  # 輸出 [2 9]

底層C實現解析

2.1.11 布爾索引的底層C實現

NumPy 的布爾索引通過內部的 C 擴展來實現。具體來說,NumPy 會遍歷布爾數組,找到所有 True 的位置,并將這些位置的元素復制到一個新的數組中。

內存復制示意圖
NumPy 數組
布爾數組
遍歷布爾數組
找到 True 位置
復制元素到新數組
輸出數組
代碼示例(C 擴展)
// 假設 arr 是一個指向 NumPy 數組的指針
int* arr = ...;
int* mask = ...;
int* result = malloc(sizeof(int) * num_true_elements);int index = 0;
for (int i = 0; i < array_size; i++) {if (mask[i]) {  // 如果布爾數組的值為 Trueresult[index] = arr[i];  // 復制元素到新數組index++;}
}
2.1.12 花式索引的底層C實現

NumPy 的花式索引通過內部的 C 擴展來實現。具體來說,NumPy 會根據整數數組中的索引值,將相應的元素復制到一個新的數組中。

內存復制示意圖
NumPy 數組
整數數組
遍歷整數數組
找到索引值
復制元素到新數組
輸出數組
代碼示例(C 擴展)
// 假設 arr 是一個指向 NumPy 數組的指針
int* arr = ...;
int* indices = ...;
int* result = malloc(sizeof(int) * num_indices);for (int i = 0; i < num_indices; i++) {result[i] = arr[indices[i]];  // 根據索引值復制元素到新數組
}

實際應用場景對比

2.1.13 布爾索引與花式索引的應用對比

布爾索引和花式索引在實際應用中各有優缺點。布爾索引適用于條件過濾,而花式索引適用于多維數組中選擇特定的子數組。

應用場景示例
# 創建一個 NumPy 數組
data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])# 布爾索引示例
filtered_data = data[data > 5]
print(filtered_data)  # 輸出 [6 7 8 9]# 花式索引示例
selected_data = data[[0, 2], [1, 2]]
print(selected_data)  # 輸出 [2 9]

參考資料

  • NumPy 官方文檔
  • NumPy 高級索引教程
  • Python 數據科學手冊
  • NumPy 布爾索引解析
  • NumPy 花式索引詳解
  • NumPy 內存管理
  • [NumPy 性能優化技巧](https://www FluentPython.com/numofrecommendation)
  • NumPy C 擴展開發指南
  • 科學計算基礎
  • [NumPy 高級索引性能測試](https://www FluentPython.com/numofbenchmarks)

這篇文章包含了詳細的原理介紹、代碼示例、源碼注釋以及案例等。希望這對您有幫助。如果有任何問題請隨私信或評論告訴我。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/67613.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/67613.shtml
英文地址,請注明出處:http://en.pswp.cn/web/67613.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

云原生(五十二) | DataGrip軟件使用

文章目錄 DataGrip軟件使用 一、DataGrip基本使用 二、軟件界面介紹 三、附件文件夾到項目中 四、DataGrip設置 五、SQL執行快捷鍵 DataGrip軟件使用 一、DataGrip基本使用 1. 軟件界面介紹 2. 附加文件夾到項目中【重要】 3. DataGrip配置 快捷鍵使用&#xff1a;C…

【Elasticsearch】match_bool_prefix 查詢 vs match_phrase_prefix 查詢

Match Bool Prefix Query vs. Match Phrase Prefix Query 在 Elasticsearch 中&#xff0c;match_bool_prefix 查詢和 match_phrase_prefix 查詢雖然都支持前綴匹配&#xff0c;但它們的行為和用途有所不同。以下是它們之間的主要區別&#xff1a; 1. match_bool_prefix 查詢…

算法基礎——存儲

引入 基礎理論的進步&#xff0c;是推動技術實現重大突破&#xff0c;促使相關領域的技術達成跨越式發展的核心。 在發展日新月異的大數據領域&#xff0c;基礎理論的核心無疑是算法。不管是技術設計&#xff0c;還是工程實踐&#xff0c;都必須仰仗相關算法的支持&#xff0…

正則表達式入門

入門 1、提取文章中所有的英文單詞 //1&#xff0e;先創建一個Pattern對象&#xff0c;模式對象&#xff0c;可以理解成就是一個正則表達式對象 Pattern pattern Pattern.compile("[a-zA-Z]"); //2&#xff0e;創建一個匹配器對象 //理解:就是 matcher匹配器按照p…

分布式架構中的事務管理:需要了解的常見解決方案

前言 在現代互聯網應用中&#xff0c;分布式架構越來越常見。隨著系統規模的擴大&#xff0c;越來越多的業務和數據被分布到不同的服務和數據庫中。雖然分布式架構帶來了諸多優勢&#xff0c;但也引入了一個新的問題&#xff1a;分布式事務。 一、什么是分布式事務&#xff1…

《TCP 網絡編程實戰:開發流程、緩沖區原理、三次握手與四次揮手》

一、 TCP 網絡應用程序開發流程 學習目標 能夠知道TCP客戶端程序的開發流程1. TCP 網絡應用程序開發流程的介紹 TCP 網絡應用程序開發分為: TCP 客戶端程序開發TCP 服務端程序開發說明: 客戶端程序是指運行在用戶設備上的程序 服務端程序是指運行在服務器設備上的程序,專門…

新年新挑戰:如何用LabVIEW開發跨平臺應用

新的一年往往伴隨著各種新的項目需求&#xff0c;而跨平臺應用開發無疑是當前備受矚目的發展趨勢。在眾多開發工具中&#xff0c;LabVIEW 以其獨特的圖形化編程方式和強大的功能&#xff0c;為開發跨平臺應用提供了有效的途徑。本文將深入探討如何運用 LabVIEW 開發能夠在不同操…

C 語言實現計算一年中指定日期是第幾天?題】

引言 在編程的世界里&#xff0c;處理日期和時間相關的問題是非常常見的。比如在日歷應用、任務管理系統、數據分析等場景中&#xff0c;經常需要計算某個日期在一年中是第幾天。本文將詳細介紹如何使用 C 語言來實現這一功能&#xff0c;通過分析代碼的結構、邏輯以及可能存在…

rsync安裝與使用-linux015

使用 rsync 可以非常高效地將文件或目錄從一個服務器傳輸到另一個服務器。 能力&#xff1a; 支持 64 位文件、64 位 inode、64 位時間戳、64 位長整型支持套接字對、符號鏈接、符號鏈接時間、硬鏈接、硬鏈接特殊文件、硬鏈接符號鏈接支持 IPv6、訪問時間&#xff08;atimes&…

UE5.3 C++ CDO的初步理解

一.UObject UObject是所有對象的基類&#xff0c;往上還有UObjectBaseUtility。 注釋&#xff1a;所有虛幻引擎對象的基類。對象的類型由基于 UClass 類來定義。 這為創建和使用UObject的對象提供了 函數&#xff0c;并且提供了應在子類中重寫的虛函數。 /** * The base cla…

Pandas基礎06(異常值的檢測與過濾/抽樣/常用聚合函數/數據聚合)

Pandas基礎06 異常值的檢測與過濾 在數據分析中&#xff0c;異常值&#xff08;Outliers&#xff09;是指與其他數據點顯著不同的值。這些值可能由于數據錄入錯誤、設備故障或極端情況而產生&#xff0c;因此在進行數據分析之前&#xff0c;需要對其進行檢測與過濾。本文將介紹…

【PyTorch】4.張量拼接操作

個人主頁&#xff1a;Icomi 在深度學習蓬勃發展的當下&#xff0c;PyTorch 是不可或缺的工具。它作為強大的深度學習框架&#xff0c;為構建和訓練神經網絡提供了高效且靈活的平臺。神經網絡作為人工智能的核心技術&#xff0c;能夠處理復雜的數據模式。通過 PyTorch&#xff0…

jstat命令詳解

jstat 用于監視虛擬機運行時狀態信息的命令&#xff0c;它可以顯示出虛擬機進程中的類裝載、內存、垃圾收集、JIT 編譯等運行數據。 命令的使用格式如下。 jstat [option] LVMID [interval] [count]各個參數詳解&#xff1a; option&#xff1a;操作參數LVMID&#xff1a;本…

App.Current.Services.GetService<UserView>()無限循環

代碼無線循環 public partial class UserView : UserControl{public UserView(){InitializeComponent();InitData();}private void InitData(){DataContext App.Current.Services.GetService<UserView>();}} } DataContext App.Current.Services.GetService<User…

(動態規劃路徑基礎 最小路徑和)leetcode 64

視頻教程 1.初始化dp數組&#xff0c;初始化邊界 2、從[1行到n-1行][1列到m-1列]依次賦值 #include<vector> #include<algorithm> #include <iostream>using namespace std; int main() {vector<vector<int>> grid { {1,3,1},{1,5,1},{4,2,1}…

松靈機器人 scout ros2 驅動 安裝

必須使用 ubuntu22 必須使用 鏈接的humble版本 #打開can 口 sudo modprobe gs_usbsudo ip link set can0 up type can bitrate 500000sudo ip link set can0 up type can bitrate 500000sudo apt install can-utilscandump can0mkdir -p ~/ros2_ws/srccd ~/ros2_ws/src git cl…

pytorch基于GloVe實現的詞嵌入

PyTorch 實現 GloVe&#xff08;Global Vectors for Word Representation&#xff09; 的完整代碼&#xff0c;使用 中文語料 進行訓練&#xff0c;包括 共現矩陣構建、模型定義、訓練和測試。 1. GloVe 介紹 基于詞的共現信息&#xff08;不像 Word2Vec 使用滑動窗口預測&…

C++ 堆棧分配的區別

這兩種聲明方式有什么區別 1.使用 new 關鍵字動態分配內存 動態分配&#xff1a;使用 new 關鍵字會在堆&#xff08;heap&#xff09;上分配內存&#xff0c;并返回一個指向該內存位置的指針。生命周期&#xff1a;對象的生命周期不會隨著聲明它的作用域結束而結束&#xff0…

深入解析 Linux 內核中的頁面錯誤處理機制

在現代操作系統中,頁面錯誤(Page Fault)是內存管理的重要組成部分。當程序試圖訪問未映射到物理內存的虛擬內存地址時,CPU 會觸發頁面錯誤異常。Linux 內核通過一系列復雜的機制來處理這些異常,確保系統的穩定性和性能。本文將深入解析 Linux 內核中處理頁面錯誤的核心代碼…

MATLAB-Simulink并行仿真示例

一、概述 在進行simulink仿真的過程中常常遇到CPU利用率較低&#xff0c;仿真緩慢的情況&#xff0c;可以借助并行仿真改善這些問題&#xff0c;其核心思想是將參數掃描、蒙特卡洛分析或多工況驗證等任務拆分成多個子任務&#xff0c;利用多核CPU或計算集群的并行計算能力&…