# Python 基本用法
###### tags: `python`
created_time: 2020-11-17 15:30
updated_time: 2022-10-26 15:15:03.887608
[TOC]
## 控制結構
if:
elif:
else:
while : 注意要有不滿足condition的一刻 不然會陷入無窮迴圈
for 變數 in 迭代物件 :
pass : 不做事
#維持程式完整 可以慢點寫完成 不會使程式誤判
break : 跳離當前迴圈
continue : 直接進入下一次迴圈
## 基本運算
### Addition and subtraction: 加與減
```
print(10+15)
print(10-15)
```
### Multiplication and division: 乘與除
```
print(10*15)
print(10/2)
```
### Exponentiation: 指數(次方)
```
print(10**2)
```
### Roots(根號)
```
print(16**0.5)
```
### Modulo: 餘數
```
print(18%7)
print(18%2)
```
### Floor Division 取整除 - 返回商的整数部分
```
print(18//7)
```
## 顯示及變數
### Print
```
# Console Out: 執行結果,於Out位置顯示
"Hi"
# print(): "印出函式"的執行結果
print("Hi")
print('Hello', 'Python')
print('Hello', 'Python', sep='__')
print('Hello', 'Python', sep=';')
```
NOTE: 執行結果在 jupyter notebook 中,僅會顯示"最後執行之輸出"
### Create Variable and Variable Assignments 創造變數與賦值
```
# Create a variable x
x = 5
```
### 同時賦值
```
a, b, c = 1, 2, 3
print('a:', a)
print('b:', b)
print('c:', c)
```
### 刪除已命名之變數
```
temp = 50
del temp
```
### 查看型態
```
var = 10
type(var)
type(False)
```
## 小技巧
### 關於註解
```
# 在 Python 當中,使用 # 作為單行註釋符號。
# 另外,使用三個 " 做為多行註釋符號。舉例如下:
"""
print("在多行註釋內的區域,內容不會被執行")
"""
```
### 關於變數命名規則(Constant and Variable Naming Conventions)
```
- 變數的命名,不只是為了賦值而已,同時也是為了讓自己在寫程式時更加清楚。
- 每個程式語言,都具有自己的命名規則(rules)與寫作風格(styles):
- 命名規則:必須遵守。否則可能會導致程式無法運行、或無法正確運行。
- 寫作風格:建議遵守,包括變數命名方式、空格使用等。參考該語言社群較流行的寫作風格,將有利開發、以及方便他人閱讀程式碼。
- 在 Python的變數命名規則中,以下是必須要遵守的項目:
- 不能夠在命名變數時,以數字做為開頭(ex: 1a 1b)。
- 不能夠在命名變數時,使用空白(可使用 _ 取代)。
- 不能夠在命名變數時,使用除了 _ 之外的特殊字元。
- 避免使用單英文單字進行命名。
- 避免使用Python內定保留字元進行命名。(ex: list, str, tuple)。
```
Python的寫作風格可參考 PEP8 https://www.python.org/dev/peps/pep-0008/
### 查看保留字
import keyword
keyword.kwlist
## 字串 String
```
phone = "iphone X"
# 對應位置示意:
string iphone X
index 01234567
# 注意 python 的範圍選取,是由 0 開始
print(phone[0])
# 'p'
print(phone[5])
# 'e'
# 可用負號倒數回來
print(phone[-1])
# 'X'
# 包前不包後
print(phone[0:3])
→ 'iph'
# 冒號之前不填數字,代表從最前開始
print(phone[:3])
# 'iph'
# 冒號之後不填數字,會包括最後一個
print(phone[0:])
# 'iphone X'
# 除了最後一個之外
phone[:-1]
# 'iphone '
# 全選
print(phone[:])
# 'iphone X'
# Error
phone[0] = 'k'
```
### 字串合併
```
first_name = "Kobe"
last_name = "Bryant"
full_name = first_name + last_name
full_name + '24'
```
### 字串乘法
```
letter = "A"
letter*10
```
### 注意字串和數字,型態不同
```
5 == '5'
# False
# This will cause Error
5 + '5'
```
### 字串的內建方法(Built-in String methods)
```
phone = "iphone X"
# 第一個字為大寫
phone.title()
# 全轉為大寫
phone.upper()
# 全轉為小寫
phone.lower()
# 以空白分割、分裂(預設是空白)
phone.split()
# 以指定字元分割、分裂
phone.split('e')
"Hello my name is SnackD".split(" ")
# ['Hello', 'my', 'name', 'is', 'SnackD']
# 取得字串長度
len(phone)
# 字串取代
phone.replace("X","!")
# 判斷第一個字元(注意大小寫式不同的!)
phone.startswith('I')
# 判斷最後一個字元
phone.endswith('X')
```
在 Pandas 中:
```
temp = pd.read_csv("csv/temp.csv").dropna(how="all")
temp["Department"] = temp["Department"].astype("category")
temp.tail(3)
temp["Name"].str.split(",").head()
temp["Name"].str.split(",").str.get(0).str.title()
temp["Name"].str.split(",").str.get(0).str.title().head()
```
### Print String with .format() method
```
# Automatic field numbering with {}
'hello {}'.format('world!')
# Manual field specification with {0} {1}...
'{2}, {1}, {0}, {3}'.format('A', 'B', 'C', 'D')
# Manual field specification with {0} {1}...
'{first}, {second}, {first}, {second}'.format(first='A', second='B')
# 在format中的值無論什麼型態,皆會直接以轉為以str表示
'{}, {}, {}'.format(1, 'kobe', True)
# 使用範例
fruit_name = 'apple'
fruit_price = 17
print('Fruit: {0}, Cost: {1} dollars.'.format(fruit_name, fruit_price))
```
### Formatted String Literals (f-strings)
python 3.6 的 String新功能(注意:版本一定要在3.6以上)
- https://cito.github.io/blog/f-strings/
- https://docs.python.org/3/reference/lexical_analysis.html#f-strings
```
name = 'Jack'
age = 22
f'He said his name is {name} and he is {age} years old.'
num = 23.45678
print("My 10 character, four decimal number is:{0:10.4f}".format(num))
print(f"My 10 character, four decimal number is:{num:{10}.{6}}")
```
## List 串列,列表
* list 有序, 且具有索引特性
* list 內可包含不同類型對象
* list 長度可變動
* list 內容可變動
References
1 https://openhome.cc/Gossip/Python/ListType.html
2 https://www.w3schools.in/python-tutorial/lists/
```
# list 有序, 且具有索引特性
num_list = [1, 3, 5, 7]
type(num_list)
# list 內可包含不同類型對象
mix_list = [100, 'apple', True]
mix_list
# 空 list
temp_list = []
print(type(temp_list), len(temp_list))
# 查看list長度
num_list = [1, 3, 5, 7]
len(num_list)
# num_list[0]
# 1
# num_list[:]
# [1, 3, 5, 7]
# num_list[1:-1]
# [3, 5]
```
### Concatenate lists 連接列表
```
first_list = [10, 20, 30]
second_list = [100, 200, 300]
total_list = first_list + second_list
total_list
# [10, 20, 30, 100, 200, 300]
# list長度可變動
first_list = first_list + [40]
# Check first_list
first_list
# [10, 20, 30, 40]
# Make the list Triple times
first_list * 3
# [10, 20, 30, 40, 10, 20, 30, 40, 10, 20, 30, 40]
# Check first_list
first_list
# [10, 20, 30, 40]
# list內容可變動
first_list[0] = 50
first_list
# [50, 20, 30, 40]
```
### Methods built in list
```
list_1 = [10, 20, 30]
list_1
# [10, 20, 30]
# Append data
list_1.append(40)
list_1
# [10, 20, 30, 40]
# Pop off item with pop(). Default popped index is -1
list_1.pop()
list_1
# [10, 20, 30]
# Check the popped item, with popped-index -2
popped_item = list_1.pop(-2)
popped_item
# 20
# Check the remain items
list_1
# [10, 30]
new_list = [50, 30, 60, 70]
alpha_list = ['A', 'C', 'B', 'F']
# Sort
new_list.sort()
new_list
# [30, 50, 60, 70]
# Reverse
alpha_list.reverse()
alpha_list
# ['F', 'B', 'C', 'A']
```
### Nested List
```
first_list = [1, 2, 3]
second_list = [4, 5, 6]
third_list = [7, 8, 9]
# Make a list of lists
nested_list = [first_list, second_list, third_list]
nested_list
# [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
# index it
nested_list[0]
# [1, 2, 3]
nested_list[1][2]
# 6
```
### Dictionary 字典
#### Dictionary 字典的使用方式可以先選擇性不看
References
1. https://openhome.cc/Gossip/Python/DictionaryType.html
1. https://www.w3schools.in/python-tutorial/dictionaries/
```
# 使用 {'key': value} 建立 dictionary
students_dict = {'Jane': 90, 'Jack': 80}
students_dict
type(students_dict)
# {'Jack': 80, 'Jane': 90}
# Call values by their key
students_dict['Jane']
# 90
# dictionary的value可為多種型態如list, 甚至是nested dict.
info_dict = {'name': 'Ken',
'age': 20,
'grades': [90, 80, 80],
'fav_fruits': {'apple': 10,
'banana': 20}
}
# Get grades which is 90
info_dict['grades'][0]
# 90
# Get apple's value
info_dict['fav_fruits']['apple']
# 10
```
#### Add key-value
```
info_dict['fav_sport'] = 'baseball'
info_dict
# {'age': 20,
# 'fav_fruits': {'apple': 10, 'banana': 20},
# 'fav_sport': 'baseball',
# 'grades': [90, 80, 80],
# 'name': 'Ken'}
```
#### Reassign values
```
info_dict['age'] = 21
info_dict
# {'age': 21,
# 'fav_fruits': {'apple': 10, 'banana': 20},
# 'fav_sport': 'baseball',
# 'grades': [90, 80, 80],
# 'name': 'Ken'}
```
### Basic methods of dict
```
# Check dict_keys
info_dict.keys()
# dict_keys(['name', 'age', 'grades', 'fav_fruits', 'fav_sport'])
# Check dict_values
info_dict.values()
# dict_values(['Ken', 21, [90, 80, 80], {'apple': 10, 'banana': 20}, 'baseball'])
# Check dict_items
info_dict.items()
# dict_items([('name', 'Ken'), ('age', 21), ('grades', [90, 80, 80]), ('fav_fruits', {'apple': 10, 'banana': 20}), ('fav_sport', 'baseball')])
# pop off specifiec item with key
info_dict.pop('name')
info_dict
# {'age': 21,
# 'fav_fruits': {'apple': 10, 'banana': 20},
# 'fav_sport': 'baseball',
# 'grades': [90, 80, 80]}
```
### Tuple
```
temp_tuple = ()
first_tuple = (10, 20, 30)
# Check length
len(first_tuple)
# index
first_tuple[0]
# 10
# tuple可存多種類型
sec_tuple = ([1, 2, 3],
50,
'apple',
{'height': 100}
)
sec_tuple[0]
# [1, 2, 3]
sec_tuple[0][0]
# 1
sec_tuple[3]
# {'height': 100}
```
#### Methods build in tuple
```
first_tuple = (10, 20, 30, 10)
# Enter a value within index(), return the value's index position.
first_tuple.index(10)
# 0
# Count the number of times a value appears
first_tuple.count(10)
# 2
```
#### Add or Re-assign
```
first_tuple = (10, 20, 30, 10)
# This will cause Error
# > TypeError: 'tuple' object does not support item assignment
# first_tuple[3] = 40
```
### set
```
grades_list = [100, 90, 90, 80, 85, 85, 85]
grades_list
# [100, 90, 90, 80, 85, 85, 85]
# set
set(grades_list)
# {80, 85, 90, 100}
no_repeat_grades = list(set(grades_list))
no_repeat_grades
# [80, 90, 100, 85]
```
### None (NoneType)
```
t = None
print(t)
# None
type(t)
# NoneType
```
### Statements | if else
References
1. https://openhome.cc/Gossip/Python/IfStatement.html
1. https://www.w3schools.in/python-tutorial/decision-making/
python 和其他類型程式語言比較:
其他類型語言:
```
if (a > 5){
DO SOMETHING
}
```
Python:
```
if a > 5:
DO SOMETHING
```
* python敘述句中,省略了() 和 {}。
* 取而代之,使用空格縮排(Indentation)、冒號(:)來控制區域。
* 請注意縮排非常重要。
```
if True:
print("因為判斷條件為True,執行此區域")
# 因為判斷條件為True,執行此區域
if False:
print("因為判斷條件為False,不會執行此區域")
```
```
# if-else為由上往下,因此若判斷條件為真,即不會執行剩餘同等級判斷句。
x = 100
if x > 80:
print("判斷條件為真,執行此區域")
else:
print("不會執行此區域")
# 判斷條件為真,執行此區域
grade = 75
if grade > 70:
print("您的分數是{}分, 判定及格。".format(grade))
else:
print("您的分數是{}分, 判定不及格。".format(grade))
# 您的分數是75分, 判定及格。
p_name = 'Kobe'
if p_name == 'Kobe':
print('Hi Kobe!')
else:
print("Who?")
# Hi Kobe!
```
```
# 判斷條件不僅一個時
grade = 63
if grade > 80:
print("您的分數是{}分, 比80高呢。".format(grade))
elif grade > 75:
print("您的分數是{}分, 比75高呢。".format(grade))
elif grade > 70:
print("您的分數是{}分, 比70高呢。".format(grade))
else:
print("剩餘的條件,都歸類在這。")
# 剩餘的條件,都歸類在這。
# 判斷條件不僅一個時
price = 250
if price > 300:
print("價格是{}, 比300高呢。".format(price))
elif 300 >= price >= 200:
print("價格是{}, 介於200~300呢。".format(price))
else:
print("剩餘的條件,都歸類在這。")
# 價格是250, 介於200~300呢。
```
* 除了明確的判斷條件(ex: x = 5, a > 6),或是True False之外。
* empty list, empty dict, empty tuple, empty string, 0 -> 都判斷為False。
```
if []:
print("不會執行呢")
if {}:
print("不會執行呢")
if 0:
print("不會執行呢")
if ():
print("不會執行呢")
if "":
print("不會執行呢")
```
```
if ["A"]:
print("會執行呢")
if {'key1': 30}:
print("會執行呢")
if 2:
print("會執行呢")
if (3, 5):
print("會執行呢")
if "hi":
print("會執行呢")
```
#### Nested if-else
```
x = 5
y = 10
if x == 10:
if y > 30:
print("A")
else:
print("B")
else:
if y == 10:
print("C")
# C
```
### Statements | loops
References
1. https://openhome.cc/Gossip/Python/ForWhileStatement.html
1. https://www.w3schools.in/python-tutorial/loops/
語法:
```
for item in object:
DO SOMETHING
```
語法要點:
```
for item in object:
 ̄ ̄ # DO SOMETHING
↑
item的變數名可自由命名,不影響loop結果
```
概念舉例:
```
for 學生姓名 in 修課學生名單:
print(學生姓名)
```
```
num_list = [1, 2, 3, 4, 5]
# 印出num_list中的數字
print(num_list[0])
#1
print(num_list[1])
#2
print(num_list[2])
#3
print(num_list[3])
#4
print(num_list[4])
#5
↓
num_list = [1, 2, 3, 4, 5]
# 用for loop印出印出num_list中的數字
for num in num_list:
print(num)
# 用 x ,也是可以執行的。
for x in num_list:
print(x)
# 1
# 2
# 3
# 4
# 5
mix_list = [('A', 20), ('B', 40), ('C', 60)]
for (x, y) in mix_list:
print(x)
print(y)
# A
# 20
# B
# 40
# C
# 60
```
```
grade_list = [80, 70, 69, 50, 92]
for grade in grade_list:
if grade > 75:
print("分數為{}, 高於75分呢!".format(grade))
# 分數為80, 高於75分呢!
# 分數為92, 高於75分呢!
num_list = [1, 2, 3, 4, 5, 6]
for num in num_list:
if num % 2 == 0:
print(num, "偶數")
else:
print(num, '奇數')
# 1 奇數
# 2 偶數
# 3 奇數
# 4 偶數
# 5 奇數
# 6 偶數
```
```
name_list = ["Kobe", "James", "Steve", "Klay"]
k_list = []
for name in name_list:
# 轉為小寫後, 判斷開頭是否為k
if name.lower().startswith('k'):
# append到k_list
k_list.append(name)
print(k_list)
# ['Kobe', 'Klay']
```
```
# string
for letter in 'Congratulations!':
print(letter)
# C
# o
# n
# g
# r
# a
# t
# u
# l
# a
# t
# i
# o
# n
# s
# !
# tuple
_tuple = (1,2,3,4,5)
for t in _tuple:
print(t)
# 1
# 2
# 3
# 4
# 5
```
```
grade_dict = {'math': 80,
'physics': 90,
'geography': 89}
# check grade_dict.keys()
grade_dict.keys()
# dict_keys(['math', 'physics', 'geography'])
for key in grade_dict.keys():
print(key)
# math
# physics
# geography
# check grade_dict.items()
grade_dict.items()
# dict_items([('math', 80), ('physics', 90), ('geography', 89)])
for key, value in grade_dict.items():
print(key, value)
# math 80
# physics 90
# geography 89
```
#### break、continue
```
# grade_list
grade_list = [10, 20, 30, 40, 50]
# count use 計數用
i = 0
for grade in grade_list:
# 當i>3為真, break 會離開該層迴圈
if i > 3:
break
# 印出 i與grade
print(i, grade)
# 每次進行到這, 計數 i = i + 1
i += 1
# 0 10
# 1 20
# 2 30
# 3 40
# count use 計數用
i = 0
for grade in grade_list:
# continue用於跳過該次迭代
if i == 3:
i += 1
continue
print(i, grade)
i += 1
# 0 10
# 1 20
# 2 30
# 4 50
```
#### 關於 pass
```
word = "python"
for letter in word:
if letter == "t":
pass
else:
print(letter)
```
### while loops
References
1. GIF animation https://blog.penjee.com/top-5-animated-gifs-explain-loops-python/
1. https://www.w3schools.in/python-tutorial/loops/
1. https://www.w3schools.in/python-tutorial/loops/
when to use "while" or "for" in python?
1. https://stackoverflow.com/questions/920645/when-to-use-while-or-for-in-python
語法:
```
while 條件:
DO SOMETHING
else:
Escape the while loop, finally DO SOMETHING
```
**請注意:判斷條件若使用不善,可能會產生infinite loop**
```
age = 10
while age < 18:
print("現在{}歲, 沒滿18歲還不能喝酒喔".format(age))
age+=1
else:
print('跳出while了, 現在{}歲!'.format(age))
# 請注意!!這會造成無限迴圈。
# 因 while條件恆為真!
# while True:
# print("卡在infinite loop=_=")
# while條件恆為真。
# 利用while內的if判斷式搭配break進行迴圈跳出。
# 請注意此種方法,else內不會被執行。
x = 10
while True:
print(x)
x += 1
if x > 15:
break
else:
print("咦?")
# 10
# 11
# 12
# 13
# 14
# 15
```
常用技巧整理
* range
http://www.runoob.com/python3/python3-func-range.html
* enumerate
http://www.runoob.com/python3/python3-func-enumerate.html
* zip
https://goo.gl/2rXdPB
http://www.cnblogs.com/yemeng/p/4063769.html
* in
https://goo.gl/pRgqz8
* list comprehension
http://python-3-patterns-idioms-test.readthedocs.io/en/latest/Comprehensions.html
#### range
```
range(5)
# range(0, 5)
list(range(5))
# [0, 1, 2, 3, 4]
for i in range(5):
print(i)
# 0
# 1
# 2
# 3
# 4
for i in range(1, 5):
print(i)
# 1
# 2
# 3
# 4
```
### enumerate
```
fruit_list = ['apple', 'banana', 'pineapple']
# get index method 1
i = 0
for item in fruit_list:
print(i, item)
i += 1
# 0 apple
# 1 banana
# 2 pineapple
# get index method 2
for item in fruit_list:
item_index = fruit_list.index(item)
print(item_index, item)
# 0 apple
# 1 banana
# 2 pineapple
# get index method 3, with range
for i in range(len(fruit_list)):
print(i, fruit_list[i])
# 0 apple
# 1 banana
# 2 pineapple
# get index method 4, with enumerate
for index, item in enumerate(fruit_list):
print(index, item)
# 0 apple
# 1 banana
# 2 pineapple
```
#### zip
```
number_list = [10, 20, 30, 40, 50]
subject_list = ['A', 'B', 'C', 'D', 'E']
zip(number_list, subject_list)
# <zip at 0x24135295b88>
list(zip(number_list, subject_list))
# [(10, 'A'), (20, 'B'), (30, 'C'), (40, 'D'), (50, 'E')]
```
#### in
參考網址:[in Operators Example](https://goo.gl/pRgqz8)
```
'p' in 'python'
# True
'A' in ['A', 'B', 'C']
# True
['A'] in ['A', 'B', 'C']
# False
('A', 'B') in [('A', 'B'), ('B', 'C') ]
# True
```
#### list comprehension
```
number_list = [10, 20, 30, 40, 50]
collection_list = []
# with for loop
for number in number_list:
collection_list.append(number)
print(collection_list)
# [10, 20, 30, 40, 50]
```
### array
```
import numpy as np
g = np.array([40, 70, 25])
g[0] #指定第一個數字
# 40
w = np.array([0.4, 0.3, 0.3])
(g*w).sum()
# 44.5
np.dot(g, w)
# 44.5
np.dot(g, 1)
# array([40, 70, 25])
grades = [77, 85, 66, 98, 0, 74, 90]
total = 0
for s in grades:
total = total + s
print(total/len(grades))
newgrades = []
for s in grades:
newgrades.append(s+5)
newgrades
# [82, 90, 71, 103, 5, 79, 95]
garr = np.array(grades)
garr
# array([77, 85, 66, 98, 0, 74, 90])
garr.mean()
# 70.0
garr.sum()
# 490
garr + 5
# array([ 82, 90, 71, 103, 5, 79, 95])
```
## Pandas
Pandas 可以想成是 Python 的 Excel, 但又更有彈性、更方便!
Pandas 基本上有兩種資料結構, 一是 DataFrame, 可以想成一個 table; 另一個是 Series, 是個有點像 array 或 list 的形態。
我們先讀入練習檔案, 做成一個 DataFrame。
```
%matplotlib inline
import pandas as pd
df = pd.read_csv("http://bit.ly/gradescsv")
df.head()
# 前 5 筆資料長怎麼樣
df.tail()
# 最後 5 筆資料
df["數學"].mean()
# 11.57
df[["英文", "數學"]]
# 選取這兩欄
df.數學.plot()
df.數學.hist(bins=15)
df.數學.std()
# 標準化
df.describe()
# 描述性資料
df.corr()
# 相關係數
```
```
# 增加一行資料
df["沒用"] = 1
# 刪除該欄位
df.drop("沒用", axis=1, inplace=True)
# 新增總級分欄位
df["總級分"] = df.sum(axis=1)
# 新增加權欄位
df["加權"] = df.英文*1.5 + df.數學 * 2
#排序,從大排到小
# df.sort_values(by="總級分", ascending=False).head()
# 重設 index 排序
df2.index = range(1,101)
df2[df2.數學 == 15]
df2[(df2.數學==15) & (df2.英文==15)]
df2[(df2.數學==15) | (df2.英文==15)]
```
基本的 loc 使用方式
基本上 loc 這樣使用
df[列的範圍, 行的範圍]
```
df.loc[2:3, "數學":"社會"]
df.loc[(2), ("社會")]
df.loc[(2), ("社會")] = -1
```
### Matplotlib 資料視覺化
到今天, matplotlib 幾乎是標準 Python 畫圖套件了! 在有 matplotlib 之前, Python 要畫圖不那麼方便, 和 Python 很多套件一樣, 有許多方案, 但各家有不同的優缺點, 也沒有一套是大家都在用的。
```
# from IPython.display import YouTubeVideo
# YouTubeVideo('e3lTby5RI54')
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
x = np.linspace(-10,10,100)
y = np.sin(x)
plt.plot(x,y,'r')
plt.plot(x,y,'r-.')
```
#### 【技巧】快速改變線條風格
| 參數 | 說明 |
|---|---|
| `--` | dash |
| `-.` | 點 + dash |
| `:` | 點點 |
| `o` | 大點點 |
| `^` | 三角 |
| `s` | 方塊 |
#### 基本的修飾
| 參數 | 說明 |
|---|---|
| `alpha` | 透明度 |
| `color` (`c`)| 顏色 |
| `linestyle` (`ls`) | 線條風格 |
| `linewidth` (`lw`) | 線寬 |
```
r = 3
t = np.linspace(-2*np.pi, 2*np.pi, 200)
x = r*np.cos(t)
y = r*np.sin(t)
plt.plot(x, y, lw=3)
ax = plt.gca()
ax.set_aspect('equal')
plt.plot(x, y, lw=3)
r = np.sin(5*t)
```
#### subplot 畫多個圖
我們每次畫圖的時候, matplotlib 就弄 1 個 figure 畫圖區出來, 裡面可以有很多子圖, 在 figure 裡叫 axes。目前我們都只有 1 個 figure 內含 1 張圖, 所以都不用設, 現在我想畫 4 張圖時。我們就要先想好「陣式」。
比如說 2x2 這樣排列的 4 張圖。
```
x = np.linspace(0, 10, 100)
plt.subplot(221)
plt.plot(x, np.sin(x), c='#e63946', lw=3)
plt.subplot(222)
plt.plot(x, np.sin(3*x), c='#7fb069', lw=3)
plt.subplot(223)
plt.scatter(x, np.random.randn(100), c='#daa73e', s=50, alpha=0.5)
plt.subplot(224)
plt.bar(range(10), np.random.randint(1,30,10), fc='#e55934')
```
### 進階色彩
顏色表示法 1
c = 'r'
可以用 blue (b), green (g), red (r), cyan (c), magenta (m), yellow (y), black (k), white (w)
顏色表示法 2
用一個 0 到 1 的數字表灰階, 越大越白。
c = '0.6'
顏色表示法 3
網頁常用的標準 16 進位 RGB 表示法。
c = '#00a676'
我們怎知哪裡可選顏色呢? 可以用之前彥良介紹的 Coolors.co 等。
顏色表示法 4
用 0-1 的數字表 RGB 也可以。
c=(0.7, 0.4, 1)
#### marker 可以設的參數
```
x = np.linspace(-10,10,200)
y = np.sinc(x)
plt.plot(x,y, c = '#00a676', lw=3)
```
```
x = range(20)
y = np.random.randn(20)
plt.plot(x, y, marker='o')
plt.plot(x, y, c='#6b8fb4', lw=5, marker='o', mfc='#fffa7c', mec="#084c61", mew=3, ms=20)
```
| 參數 | 說明 |
|---|---|
| `marker` | marker 的風格 |
| `markeredgecolor` (`mec`) | 邊線顏色 |
| `markeredgewidth` (`mew`) | 邊線寬度 |
| `markerfacecolor` (`mfc`) | marker 的顏色 |
| `markerfacecoloralt` (`mfcalt`) | marker 替換色 |
| `markersize` (`ms`) | marker 大小 |
| `markevery` | 隔多少畫一個 marker |
#### bar
```
plt.bar(range(1,6), np.random.randint(1,30,5))
```
#### 雙色的長條圖
```
x = np.arange(1,6)
plt.bar(x - 0.4, [3, 10, 8, 12, 6], width=0.4, ec='none', fc='#e63946')
plt.bar(x, [6, 3, 12, 5, 8], width=0.4, ec='none', fc='#7fb069')
```
#### 疊加型的資料
```
A = np.random.randint(2,15,5)
B = np.random.randint(2,15,5)
C = np.random.randint(2,15,5)
plt.bar(x, A, fc='#e63946', ec='none')
plt.bar(x, B, fc='#7fb069', ec='none', bottom = A)
plt.bar(x, C, fc='#e55934', ec='none', bottom = A+B)
```
#### 橫放的長條圖
```
x = np.arange(0.6, 6)
plt.barh(x, np.random.randint(1,15,6), fc='#e55934', ec='none')
```
#### 雙向的長條圖
```
x = np.arange(0.6,6)
A = np.random.randint(1,15,6)
B = np.random.randint(1,15,6)
plt.barh(x, A, fc='#e63946', ec='none')
plt.barh(x, -B, fc='#7fb069', ec='none')
```
#### 畫圖區的設定
```
plt.title("My lovely sin function")
plt.xlabel('x-axes')
plt.ylabel('values')
plt.xlim(-6,6)
plt.ylim(-1.2,1.2)
plt.plot(x, y, lw=3, label='$\sin$')
plt.plot(x, np.cos(x), lw=3, label='$\cos$')
plt.legend()
```
#### xticks
```
xv = np.linspace(0, 2*np.pi, 100)
yv = np.sin(xv)
plt.plot(xv,yv,lw=3)
plt.xticks([0, np.pi/2, np.pi, 3*np.pi/2, 2*np.pi],
['$0$', '$\pi/2$', '$-\pi$', '$-3\pi/2$', '$-2\pi$']);
```
#### 取得現在工作中 axes
```
ax = plt.gca()
ax.set_facecolor('#69b8bb')
ax.set_xlim(-6,6)
ax.set_ylim(-1.2,1.2)
plt.plot(x,y,lw=5,c='white')
移動 x, y 座標軸
ax = plt.gca()
ax.set_facecolor('#69b8bb')
ax.set_xlim(-6,6)
ax.set_ylim(-1.2,1.2)
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines['bottom'].set_position(('data',0))
ax.spines['left'].set_position(('data',0))
plt.plot(x,y,lw=5,c='white')
```
#### 中文顯示問題
```
import matplotlib.font_manager as fm
myfont = fm.FontProperties(fname="/Users/mac/Library/Fonts/NotoSansHant-Medium.otf")
x = np.linspace(-2*np.pi, 2*np.pi, 200)
y = np.sin(x)
plt.plot(x, y, lw=5)
plt.title("我可愛的 sin 函數", fontproperties=myfont, size=20)
# 方法 2: 完完全全改過來
# 再來我們可以用 matplotlib 的參數設定, rcParams, 把字型完完全全用某個中文字型。
plt.rcParams['font.sans-serif'] = ['SimHei']
# 選個普通的黑體字
plt.rcParams['axes.unicode_minus']=False
# 負號不出問題
plt.plot(x, y, lw=5)
plt.title("我可愛的 sin 函數", size=15)
# 不用再設字型!
```
#### 耍寶可愛的 xkcd
```
save_state = plt.rcParams.copy()
plt.xkcd()
x = np.linspace(-5, 5, 200)
y = np.sin(2*x) + 0.2*x
plt.plot(x,y)
plt.rcParams.update(save_state)
```
#### seaborn 大救星
```
import seaborn as sns
sns.set(color_codes=True)
x = np.linspace(-10,10,200)
y = np.sinc(x)
plt.plot(x,y)
```
### Merge (DataFrame) 欄位合併
| 參數 | data1 |
| - | - |
| left | 參與合併的左側DataFrame |
| right| 參與合併的右側DataFrame |
| how| 連線方式:'inner'(預設);還有 'outer'、'left'、'right’ |
| on | 用於連線的列名,必須同時存在於左右兩個DataFrame物件中,如果位指定,則以left和right列名的交集作為連線鍵 |
| left_on | 左側DataFarme中用作連線鍵的列 |
| right_on |右側DataFarme中用作連線鍵的列 |
| left_index| 將左側的行索引用作其連線鍵 |
| right_index| 將右側的行索引用作其連線鍵 |
| sort| 根據連線鍵對合並後的資料進行排序,預設為True。有時在處理大資料集時,禁用該選項可獲得更好的效能 |
| suffixes | 字串值元組,用於追加到重疊列名的末尾,預設為(‘_x’,‘_y’).例如,左右兩個DataFrame物件都有‘data’,則結果中就會出現‘data_x’,‘data_y’ |
| copy | 設定為False,可以在某些特殊情況下避免將資料複製到結果資料結構中。預設總是賦值 |
```
df1 = pd.DataFrame({'key':['a','b','c'],'data1':range(3)})
```
| key | data1 |
| - | - |
| a | 0 |
| b | 1 |
| c | 2 |
```
df2 = pd.DataFrame({'key':['a','b','d'],'data2':range(3)})
```
| key | data1 |
| - | - |
| a | 0 |
| b | 1 |
| d | 2 |
```
pd.merge(df1,df2)
# 預設為 inner
pd.merge(df1,df2,how = 'inner')
# 交集
# pd.merge(df1,df2,on='key',how = 'inner')
```
| key | data1 |data2|
| - | - | -|
| a | 0 |0|
| b | 1 |1|
```
pd.merge(df1,df2,how = 'outer')
# 聯集
# pd.merge(df1,df2,on='key',how = 'outer')
```
| key | data1 |data2|
| - | - | -|
| a | 0 |0|
| b | 1 |1|
| c | 2 |NaN|
| d | NaN |1|
```
pd.merge(df1,df2,how = 'left')
# 以左側資料為主取全部,右側取部分
# pd.merge(df1,df2,on='key',how = 'left')
```
| key | data1 |data2|
| - | - | -|
| a | 0 |0|
| b | 1 |1|
| c | 2 |NaN|
```
pd.merge(df1,df2,how = 'right')
# 以右側資料為主取全部,左側取部分
# pd.merge(df1,df2,on='key',how = 'right')
```
| key | data1 |data2|
| - | - | -|
| a | 0 |0|
| b | 1 |1|
| d | NaN |1|
如果左右側DataFrame的連線鍵列名不一致,但是取值有重疊,可使用left_on、right_on來指定左右連線鍵。
#### 多對多合併 (兩個表的連線鍵 row 中有重複的情況)
```
df3 = pd.DataFrame({'key':['a','b','c','d','e'],'data1':range(5)})
```
| key | data1 |
| - | - |
| a | 0 |
| b | 1 |
| c | 2 |
| d | 3 |
| e | 4 |
```
df4 = pd.DataFrame({'key':['e','e','e','f','g'],'data2':range(5)})
```
| key | data1 |
| - | - |
| e | 0 |
| e | 1 |
| e | 2 |
| f | 3 |
| g | 4 |
```
pd.merge(df3,df4,'inner')
```
| key | data1 |
| - | - |
| e | 0 |
| e | 1 |
| e | 2 |
```
pd.merge(df3,df4,'outer')
```
| key | data1 |data2|
| - | - | -|
| a | 0 |NaN|
| b | 1 |NaN|
| c | 2 |NaN|
| d | 3 |NaN|
| e | 4 |0|
| e | 4 |1|
| e | 4 |2|
| f | NaN |3|
| g | NaN |4|
#### 索引上的合併
當連線鍵位於索引中時,成為索引上的合併,可以通過merge函式,傳入left_index、right_index來說明應該被索引的情況。
一表中連線鍵是索引列、另一表連線鍵是非索引列
```
left = pd.DataFrame({'key':['a','b','a','a','b','c'],'value': range(6)})
```
| key| value |
| - | - |
| a | 0 |
| b | 1 |
| a | 2 |
| a | 3 |
| b | 4 |
| c | 5 |
```
right = pd.DataFrame({'group_val':[1,2]},index = ['a','b'])
```
| | group_val |
| - | - |
| a | 1 |
| b | 2 |
```
pd.merge(left,right,left_on = 'key',right_index = True)
```
| key | value | group_val |
| --- | ----- | --------- |
| a | 0 | 1 |
| a | 2 | 1 |
| a | 3 | 1 |
| b | 1 | 2 |
| b | 4 | 3 |
#### 兩個表中的索引列都是連線鍵
```
left = pd.DataFrame(np.arange(6).reshape(3,2),index = ['a','b','c'],columns = ['col1','col2'])
```
| | col1 |col2|
|-| - | - |
| a | 0 |1|
| b | 2 |3|
| c | 4 |5|
```
right = pd.DataFrame(np.arange(7,15).reshape(4,2),index = ['b','c','d','e'],columns = ['col3','col4'])
```
| | col1 |col2|
|-| - | - |
| b | 7 |8|
| d | 9 |10|
| d | 11 |12|
| e | 13 |14|
```
pd.merge(left,right,left_index = True,right_index= True,how = 'outer')
```
| col1 | col2 | col3 | col4 |
| ---- | ---- | ---- | ---- |
| 0 | 1 | NaN | NaN |
| 2 | 3 | 7 | 8 |
| 4 | 5 | 9 | 10 |
| NaN | NaN | 11 | 12 |
### Concat (Series、DataFrame)