python-資料分析-NumPy的應用-1、基礎

little小新發表於2024-06-09

1、安裝python 資料分析的三大神器

pip install numpy pandas matplotlib

NumpPy 的說明

Numpy 是一個開源的 Python 科學計算庫,用於快速處理任意維度的陣列。Numpy 支援常見的陣列和矩陣操作、
對於同樣的數值計算任務,使用 NumPy 不僅程式碼要簡潔的多,而且 NumPy 在效能上也遠遠優於原生 Python、
至少是一到兩個數量級的差距,而且資料量越大,NumPy 的優勢就越明顯。

NumPy 最為核心的資料型別是ndarray,使用ndarray可以處理一維、二維和多維陣列,該物件相當於是一個快速而靈活的大資料容器。
NumPy 底層程式碼使用 C 語言編寫,解決了 GIL 的限制,ndarray在存取資料的時候,資料與資料的地址都是連續的,
這確保了可以進行高效率的批次操作,效能上遠遠優於 Python 中的list;另一方面ndarray物件提供了更多的方法來處理資料,
尤其獲取資料統計特徵的方法,這些方法也是 Python 原生的list沒有的。

numpy模組的基礎使用

# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import numpy
import pandas
import matplotlib

#建立陣列物件 - ndarray 建立ndarry有多種方法
# 1、是哦那個array函式、透過list建立陣列物件
array1 = numpy.array([1, 2, 3, 4, 5])
print(array1)   #[1 2 3 4 5]
array2 = numpy.array([[1, 2, 3], [4, 5, 6]])    #輸出會自動換行
print(array2)
#[[1 2 3]
# [4 5 6]]

# 2、使用arange函式、指定取值範圍和跨度建立陣列物件
# arange(start, stop, step)
array3 = numpy.arange(0, 20, 2)
print(array3)   #[ 0  2  4  6  8 10 12 14 16 18]

# 3、使用linspace函式、用指定範圍和元素個數建立陣列物件、生成等差數列
# linspace(start, stop, num)
array4 = numpy.linspace(-1, 1, 11)
print(array4)   #[-1.  -0.8 -0.6 -0.4 -0.2  0.   0.2  0.4  0.6  0.8  1. ]


# 4、使用logspace函式、生成等比數列
# logspace(start, stop, num, base)
#start=1表示2的1次方
#stop=10表示2的10次方
#num=10表示生成10個數
#base=2表示以2為底
array5 = numpy.logspace(1, 10, num=10, base=2)  ##含義是生成 10 個數,這些數在對數基數為 2的刻度上從 2的1次方到2的10次方均勻的分佈
print(array5)   #[   2.    4.    8.   16.   32.   64.  128.  256.  512. 1024.]

#注意:等比數列的起始值是$2^1$,等比數列的終止值是$2^{10}$,num是元素的個數,base就是底數。

# 5、透過fromstring函式從字串提取資料建立陣列物件
# fromstring(string, sep, dtype)
# string:字串
# sep:分隔符
# dtype:資料型別 i8表示int64
array6 = numpy.fromstring('1 2 3 4 5', sep=' ', dtype='i8')
print(array6)   #[1 2 3 4 5]

# 6、 透過fromiter函式從生成器(迭代器)中獲取資料建立陣列物件
def fib(how_many):
    a, b = 0, 1
    for _ in range(how_many):   # _ :表示忽略變數
        a, b = b, a + b         #生成斐波那契數列
        yield a
gen = fib(20)
array7 = numpy.fromiter(gen, dtype='i8')
print(array7)
'''
[   1    1    2    3    5    8   13   21   34   55   89  144  233  377
  610  987 1597 2584 4181 6765]
'''

# 7、 使用numpy.random模組的函式生成隨機數建立陣列物件
#產生10個$[0, 1)範圍的隨機小數
array8 = numpy.random.rand(10)
print(array8)
"""
[0.97779416 0.65321969 0.92930144 0.77446802 0.8259189  0.40632253
 0.04318595 0.75099474 0.28481314 0.46203626]
"""

#產生10個$[1, 100)$範圍的隨機整數,程式碼:
array9 = numpy.random.randint(1, 100, 10)
print(array9)

#產生20個$\small{\mu=50}$,$\small{\sigma=10}$的正態分佈隨機數,程式碼:
array10 = numpy.random.normal(50, 10, 20)
print(array10)

#產生$[0, 1)$範圍的隨機小數構成的3行4列的二維陣列,程式碼:
#numpy.random.rand(3, 4) -> 3行4列的二維陣列
array11 = numpy.random.rand(3, 4)
print(array11)
'''
[[0.2151178  0.39222962 0.65308132 0.55345128]
 [0.34604538 0.02472764 0.3164634  0.57257634]
 [0.5175043  0.10675846 0.45963431 0.64124903]]
'''

#產生$[1, 100)$範圍的隨機整數構成的三維陣列,程式碼:
#numpy.random.randint(1, 100, (3, 4, 5)) -> 4行5列的三維陣列
array12 = numpy.random.randint(1, 100, (3, 4, 5))
print(array12)
'''
[[[26  8 15 35  4]
  [85 33 74 36 18]
  [69 73 29 26 92]
  [82  3 58  8 68]]

 [[98 71 32 35 24]
  [57 51 91 73 81]
  [88 32 18 84 60]
  [25 43 89 23 18]]

 [[23 50 16 40 32]
  [90 86 13 88 24]
  [35 83 30 50 45]
  [28 69 34  1 40]]]
'''

# 8、 建立全0、全1或指定元素的陣列
#zeros(shape, dtype=float)
#shape:陣列形狀,如(3, 4)表示3行4列
#dtype:資料型別,預設為float
array13 = numpy.zeros((3, 4))   #全0
print(array13)
'''
[[0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]]
'''

#ones(shape, dtype=float)
array14 = numpy.ones((3, 4))   #全1
print(array14)


#使用full函式,程式碼:
#full(shape, fill_value, dtype=None)
#shape:陣列形狀,如(3, 4)表示3行4列
#fill_value:填充值
#dtype:資料型別,預設為float
array15 = numpy.full((3, 4), 10)
print(array15)
'''
[[10 10 10 10]
 [10 10 10 10]
 [10 10 10 10]]
'''
print("\n")
# 9、使用eye函式建立單位矩陣
#eye(N, M=None, k=0, dtype=float)
#N:矩陣的行數
#M:矩陣的列數,預設為N
#k:對角線偏移量,預設為0,表示對角線為1
#dtype:資料型別,預設為float
# array16 = numpy.eye(4, 4)
numpy.eye(4)
print(numpy.eye(4))
'''
[[1. 0. 0. 0.]
 [0. 1. 0. 0.]
 [0. 0. 1. 0.]
 [0. 0. 0. 1.]]
'''
print("\n")
# 10、讀取圖片獲得對應的三位陣列
array17 = plt.imread('images/1.jpg')    #import matplotlib.pyplot as plt
print(array17)
#計算機系統中的圖片通常由若干行若干列的畫素點構成,而每個畫素點又是由紅綠藍三原色構成的,剛好可以用三維陣列來表示。讀取圖片用到了matplotlib庫的imread函式

陣列物件的屬性

# -*- coding: utf-8 -*-
#陣列物件的屬性

import numpy
import matplotlib
import pandas

# 1、 size屬性:獲取陣列元素個數
array1 = numpy.arange(1, 100, 2)    # 生成一個1-99之間,步長為2的陣列
# print(array1)
print(array1.size)  #50
array2 = numpy.random.rand(3, 4)  # 生成一個3行4列的隨機陣列
print(array2.size)  #12

# 2、shape獲取陣列的形狀
print(array1.shape) #(50,) 50個元素
print(array2.shape) #(3, 4) 3行4列

# 3、dtype屬性、獲取陣列元素的資料型別
print(array1.dtype) #int32
print(array2.dtype) #float64

# -*- coding: utf-8 -*-
#陣列物件的屬性

import numpy
import matplotlib
import pandas

# 1、 size屬性:獲取陣列元素個數
array1 = numpy.arange(1, 100, 2)    # 生成一個1-99之間,步長為2的陣列
# print(array1)
print(array1.size)  #50
array2 = numpy.random.rand(3, 4)  # 生成一個3行4列的隨機陣列
print(array2.size)  #12

# 2、shape獲取陣列的形狀
print(array1.shape) #(50,) 50個元素
print(array2.shape) #(3, 4) 3行4列

# 3、dtype屬性、獲取陣列元素的資料型別
print(array1.dtype) #int32
print(array2.dtype) #float64

# 4、ndim屬性:獲取陣列的維度
print(array1.ndim)  #1  表示陣列是1維的
print(array2.ndim)  #2 表示陣列是二維的

# 5、itemsize屬性:獲取陣列單個元素佔用記憶體空間的位元組數
print(array1.itemsize)  #4 表示陣列中每個元素佔用4個位元組
print(array2.itemsize)  #8 表示陣列中每個元素佔用8個位元組

# nbytes屬性:獲取資料所有元素佔用記憶體空間的位元組數
print(array1.nbytes)    #200 表示陣列中每個元素佔用4個位元組,總共50個元素
print(array2.nbytes)    #96 表示陣列中每個元素佔用8個位元組,總共12個元素

ndarray物件元素的資料型別可以參考如下所示的表格

python-資料分析-NumPy的應用-1、基礎

陣列的索引運算

# -*- coding: utf-8 -*-
#陣列的索引運算
'''
和 Python 中的列表類似,NumPy 的ndarray物件可以進行索引和切片操作,透過索引可以獲取或修改陣列中的元素,透過切片操作可以取出陣列的一部分,我們把切片操作也稱為切片索引。
'''

import numpy

# 1、普通索引
#類似於python中list型別的索引運算
array1 = numpy.arange(1, 10)
print(array1)   #[1 2 3 4 5 6 7 8 9]
print(array1[0], array1[array1.size - 1])   #1 9    #array1.size 獲取陣列長度
print(array1[-array1.size], array1[-1])     #1 9

#numpy.array() 建立陣列
array2 = numpy.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(array2[2])    #[7 8 9]

print(array2[0][0]) #1
print(array2[-1][-1])   #9

print(array2[1][1]) #5
print(array2[1, 1]) #5  array2[1, 1] == array2[1][1]

array2[1][1] = 10   #修改陣列元素、賦值
print(array2)
'''
[[1 2 3]
 [4 10 6]
 [7 8 9]]
'''

array2[1] = [10, 11, 12]    #修改陣列元素、賦值
print(array2)
'''
[[1 2 3]
 [10 11 12]
 [7 8 9]]
'''
print("\n")


#2、切片索引
#切片索引是形如[開始索引:結束索引:跨度]的語法,透過指定開始索引(預設值無窮小)、結束索引(預設值無窮大、等於最大的行數或列數)和跨度(預設值1)
#因為開始索引、結束索引和步長都有預設值,所以它們都可以省略,如果不指定步長,第二個冒號也可以省略
#一維陣列的切片運算跟 Python 中的list型別的切片非常類似,此處不再贅述,二維陣列的切片可以參考下面的程式碼
array3 = numpy.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(array3)
#array3[選擇行, 選擇列]
print(array3[:2, 1:])  #:2 = 0:2:1 選擇前兩行(第0行和第1行)。   #1: = 1:3:1 選擇從第二列(第1列)到末尾的所有列
'''
#這樣看 
第 0 1  2 列
 [[1 2 3]    #第0行
  [4 5 6]    #第1行
  [7 8 9]]
 
#輸出
[[2 3]
 [5 6]]
'''

print(array3[2, :]) #2 第二行 、[:] = 0:3:1 選擇所有列   #[7 8 9]

print(array3[:, :2])    #[:, :2] = 0:3:1, 0:2:1 = 選擇所有行、第0列到第1列(第0列和第1列)
'''
[[1 2]
 [4 5]
 [7 8]]
'''

print(array3[::2, ::2]) #[::2, ::2] = 0:3:2, 0:3:2 = 選擇所有行、所有列,跨度是2
'''
[[1 3]
 [7 9]]
'''

print(array3[::-2, ::-2])   #[::-2, ::-2] = 3:0:-2, 3:0:-2 = 選擇所有行、所有列,跨度是-2
'''
[[9 7]
 [3 1]]
'''

圖1:二維陣列的普通索引

python-資料分析-NumPy的應用-1、基礎

二維陣列的切片索引

python-資料分析-NumPy的應用-1、基礎

花式索引

# -*- coding: utf-8 -*-
#花式索引
#花式索引是用儲存整數的陣列充當一個陣列的索引,這裡所說的陣列可以是 NumPy 的ndarray,也可以是 Python 中list、tuple等可迭代型別,可以使用正向或負向索引。

import numpy
array1 = numpy.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
# print(array1)
print(array1[[0, 1, 1, -1, -2, 2]])  #[1 2 2 9 8 3]

print("-------------------")

array2 = numpy.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) #3維陣列
print(array2[[0, 2]])  #array2[[0, 2]] 表示獲取array2的第0行和第2行

print("-------------------")
print(array2)
print(array2[[0, 2], [1, 2]])   #array2[[0, 2], [1, 2]] 表示獲取array2的第0行第一列、第二行的第二列
#可以這樣看[0][1] [2][2]
'''
[[1 2 3]
 [4 5 6]
 [7 8 9]]

[2 9]   #拿到的值
'''
print("-------------------")
print(array2[[0, 2], 1])    #array2[[0, 2], 1] 表示獲取array2的第0行的第1列和第2行的第1列
'''
[[1 2 3]
 [4 5 6]
 [7 8 9]]

[2 8]
'''

布林索引

# -*- coding: utf-8 -*-
#布林索引
#布林索引就是透過儲存布林值的陣列充當一個陣列的索引,布林值為True的元素保留,布林值為False的元素不會被選中。布林值的陣列可以手動構造,也可以透過關係運算來產生。

import numpy

array = numpy.array([1, 2, 3, 4, 5, 6])
array2 = numpy.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(array[[True, False, True, False, True, False]])   #[1 3 5]
print('---------------------------')

print(array > 5)    #[False False False False False  True]
print('---------------------------')
#~: 取反
print(~(array > 5)) #[ True  True  True  True  True False]
print('---------------------------')

print(array % 2 == 0)   #[False  True False  True False  True]
print('---------------------------')

print(array2[array2 % 2 == 0])  #[2 4 6 8]
print('---------------------------')

print((array > 5) & (array % 2 == 0))   #[False False False False False  True]
#說明:&運算子可以作用於兩個布林陣列,如果兩個陣列對應元素都是True,那麼運算的結果就是True,否則就是False,
# #該運算子的運算規則類似於 Python 中的 and 運算子,只不過作用的物件是兩個布林陣列
print('---------------------------')

print(array[(array > 5) & (array % 2 == 0)])    #[6]
print('---------------------------')

print(array[(array > 5) | (array % 2 == 0)])    #[2 4 6]
#說明:|運算子可以作用於兩個布林陣列,如果兩個陣列對應元素都是False,那麼運算的結果就是False,否則就是True,
# 該運算子的運算規則類似於 Python 中的 or 運算子,只不過作用的物件是兩個布林陣列。
print('---------------------------')

案例:透過陣列切片處理影像

可以用三維陣列來表示影像,那麼透過影像對應的三維陣列進行操作,就可以實現對影像的處理,如下所示。

# -*- coding: utf-8 -*-
#案例、透過陣列切片處理影像
import matplotlib.pyplot as plt
import numpy
import matplotlib

#讀入圖片建立三位陣列物件
guido_img = plt.imread('images/2.jpg')  # 讀取圖片
plt.imshow(guido_img)   # 顯示圖片

print(plt.imshow(guido_img))    #AxesImage(size=(2307, 3461))

#對陣列的0軸進行反向切片,實現影像的垂直翻轉。
print(plt.imshow(guido_img[::-1]))

相關文章