---
# System prepended metadata

title: 4/30 Python與資料分析#8 - Numpy
tags: [python, 資料分析]

---

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

