# 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` `資料分析`