# 4/30 Python與資料分析#8 - Numpy 提供題目的網站(依照簡單到難) codewars hackerrank leetcode 在jupyter 按z可以還原儲存格操作 ## Numpy簡介 Numpy = Numeric(函數) + Numarray(多維度陣列) 2005合併 import numpy as np print(np.__version__) print(np.__file__) 輸出版本/路徑 ### Numpy的特性 Python有各種型別且非常有彈性,可以互相包含,缺點是運算效能會降低(例如浪費在檢查各自類型);Numpy使用fixed-type,彈性降低但效率會增加 ``` heterogeneous_list = [5566, 55.66, True, False, '5566'] print(type(heterogeneous_list)) for i in heterogeneous_list: print(type(i)) ``` <class 'list'> <class 'int'> <class 'float'> <class 'bool'> <class 'bool'> <class 'str'> 即使都放在一起,各自類型不同,可以運算的情況可能也不同 ``` homogeneous_arr = np.array(heterogeneous_list) print(type(homogeneous_arr)) for i in homogeneous_arr: print(type(i)) ``` <class 'numpy.ndarray'> <class 'numpy.str_'> <class 'numpy.str_'> <class 'numpy.str_'> <class 'numpy.str_'> <class 'numpy.str_'> 此時所有元素都是np裡面的string型態 ex. 將某個list元素全部取倒數,可利用list comprehension,但此法需要for loop檢查每個元素是否可以運算,若用ndarray視為一體直接運算,需要的時間會比較短(但若有元素無法運算就完全不會運算) ## 創造array ### 從既有的list或tuple list1 = [....] arr1 = np.array(list1) 就可以把原來的list1變成一個array了 ### 創造相同值的array ``` print(np.zeros(5)) print(np.ones(5)) print(np.full(5, 6.0)) ``` [0. 0. 0. 0. 0.] [1. 1. 1. 1. 1.] [6. 6. 6. 6. 6.] ### 利用generator 創造等距array np.arange(頭,尾(不包含),間隔) np.linspace(頭,尾(包含),個數),個數預設50 創造隨機array(random套件) np.random.random(個數) np.random.normal(平均,標準差,個數) 常態分布取值 np.random.randint(頭,尾(不包含),個數) 只取整數 ## array的屬性attributes ndim 維度數 shape 尺寸 size 元素數 dtype 元素資料型態(所有資料型態都一樣) 操作方式都是array名稱.屬性 ``` arr = np.array([5, 5, 6, 6]) print(arr.ndim) print(arr.shape) print(arr.size) print(arr.dtype) ``` 1 (4,) 4 int64 ### 維度 Scalar: 0-dimension Vector: 1-dimension Matrix: 2-dimension Tensor: 3-dimension or more ``` scalar = np.array(5566) print(scalar) print(scalar.ndim) print(scalar.shape) ``` 5566 0 () ``` vector = np.array([5566]) print(vector) print(vector.ndim) print(vector.shape) ``` [5566] 1 (1,) ``` matrix = np.array([5, 5, 6, 6]).reshape(2, 2) # reshape(列數,行數) print(matrix) print(matrix.ndim) print(matrix.shape) ``` [[5 5] [6 6]] 2 (2, 2) ``` tensor = np.array([5, 5, 6, 6]*3).reshape(3, 2, 2) print(tensor) print(tensor.ndim) print(tensor.shape) ``` [[[5 5] [6 6]] [[5 5] [6 6]] [[5 5] [6 6]]] 3 (3, 2, 2) ## array的index/slicing 一維array索引方式同list 二維以上的索引會用[x,y,...],也可用[x][y] (若對照巢狀list,"只能"用[x][y]) array索引彈性更大,某個方向全部都要取值的話,可用:表示 例如[:,3]可以取第四欄(list做不到),若某個方向只要取某個範圍,可用[a,b],例如[:,[2,5]] slicing: array[star stop step] 若全部的話用:代替 (list也可) ### Fancy Indexing 若要索引某特定超過一個以上(但因為無規律而無法用slicing的方法)的值,可以直接用list表示想要索引的值(list無法這樣做) ``` np.random.seed(0) arr = np.random.randint(1, 100, size=(10,)) odd_indices = [0, 2, 8] print(arr) print(arr[odd_indices]) ``` [45 48 65 68 68 10 84 22 37 88] [45 65 37] ### Boolean Indexing ``` is_odd = [True, False, True, False, False, False, False, False, True, False] print(arr[is_odd]) ``` [45 65 37] 在index的list下boolean值,可印出相對於是True的值 若True的值有規則,index的list可以寫成如下(舉例,想要挑出奇數) ``` is_odd = arr % 2 == 1 print(is_odd) print(arr[is_odd]) ``` [ True False True False False False False False True False] [45 65 37] 若在list上無法如此操作,可以用filter搭配lambda代替 ## 調整array外型的操作 array名.reshape(a,b,...) a,b,...為新的尺寸 若想讓程式自己算,其中一個可以用-1代替 array名.ravel() 讓array變成一維,不須參數 np.concatenate((arr1, arr2, ...), axis= ) 必須把array們用某個結構包起來(()或[])表示iterable axis代表合併方向,從0開始 ** array的操作不會複製,原來的array更動會影響操作 若要避免此情況,可以用array名.copy()避免 (建立副本) ``` arr = np.arange(1, 10) mat = arr.copy() mat = mat.reshape(3, 3) mat[1, 1] = 5566 print(mat) print(arr) ``` [[ 1 2 3] [ 4 5566 6] [ 7 8 9]] [1 2 3 4 5 6 7 8 9] ## Numpy的函數 ### Universal Function 通用函數 輸出的結果個數等於輸入的結果個數 ``` # np.power arr = np.arange(10) print(arr) print(np.power(arr, 2)) # arr**2 ``` [0 1 2 3 4 5 6 7 8 9] [ 0 1 4 9 16 25 36 49 64 81] ``` # np.exp print(np.exp(arr)) ``` [1.00000000e+00 2.71828183e+00 7.38905610e+00 2.00855369e+01 5.45981500e+01 1.48413159e+02 4.03428793e+02 1.09663316e+03 2.98095799e+03 8.10308393e+03] 有些函數只能針對scalar做(例如abs()) 可以用 自定函數名稱 = np.vectorize(abs) 然後自定函數名稱(array名稱) 實現 abs可以改成其他函數名稱 (在list上面可以用map操作) ``` abs_ufunc = np.vectorize(abs) lst = [-5, -5, -6, -6] print(type(abs_ufunc)) print(abs_ufunc(lst)) ``` <class 'numpy.vectorize'> [5 5 6 6] ### Aggregate Function 聚合函數 * 有時候聚合可以針對某個方向 * 函數前面加nan就可以剔除遺漏值nan ``` # Aggregate along specific axis mat = np.arange(1, 16).reshape(3, 5) print(np.sum(mat)) print(np.sum(mat, axis=0)) print(np.sum(mat, axis=1)) ``` 120 [18 21 24 27 30] [15 40 65] ``` # Similar function names for array with missing values arr = np.arange(1, 16, dtype=float) arr[-1] = np.NaN print(arr) print(np.sum(arr)) print(np.nansum(arr)) ``` [ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. nan] nan 105.0 ###### tags: `python` `資料分析`