# 輕鬆學會程式交易 | Chapter 3 | Pandas
[TOC]
## 3-1 什麼是Pandas
>pandas is a fast, powerful, flexible and easy to use open source data analysis and manipulation tool,
built on top of the Python programming language.
> [name=Pandas]
> Pandas 是個快速、強大、有彈性並且易使用的開源資料分析及操作工具,基於python程式語言
> [name=Pandas官網標題]
### 下載套件
請在 Ipython Console 中輸入以下兩行程式下,即可下載
```python=+
pip install pandas # pandas套件
pip install pandas_datareader # pandas 擴充套件,下載數據專用
```
## 3-2 DataFrame 和 Series
pandas中有個最重要的變數型態叫作DataFrame。我們直接叫一個DataFrame出來具體的介紹一下它。
首先我們先從檔案匯入台積電的日線資料。
### 開啟檔案/下載資料
呼叫及使用套件。尾端使用`as`即可替套件重新取名字。
```python=
import pandas as pd
```
請注意:檔案與程式碼需在同一個資料夾
1. 開啟`csv`檔
pd.read_csv是一個函式,功能是讀取一個.csv檔案並且用DataFrame的變數型態表示它。
```python=+
twic = pd.read_csv('2330twic.csv', index_col='DATE')
```
2. 或從`Excel`檔案中開啟
簡單一行開啟,是不是很方便呀!
```python=+
twic = pd.read_excel('2330twic.xlsx', index_col='DATE')
```
3. 使用`pandas_datareader`套件下載股價資料
```python=+
# pip install pandas_datareader
import pandas_datareader as pdr
twic = pdr.DataReader('2330.TW','yahoo')
```
這時候就可以在spyder裡面的variable navigator看到我們匯入的資料了。
我接下來要介紹一下這個DataFrame。
DataFrame有直行橫列,最上方的這一橫排標示著這每一行的名稱,最左方的這一直列標示每一列的index(編號)。
1. 可以用`columns屬性`得到所有行的名稱
2. 用`shape屬性`得到DataFrame的形狀(大小)。
3. 用`len()函式`來得到rows的數量
```python=+
print(twic.shape)
print(twic.columns)
print(len(twic))
```
```python
out: (1220, 6)
out: Index(['High', 'Low', 'Open', 'Close', 'Volume', 'Adj Close'], dtype='object')
out: 1220
```
### 存取數據、切片
#### 存取columns
pandas在存取每個column的時候,是採取很像字典的方式,透過字串去索引。在製造一個新的column時,也事像,字典一樣直接宣告即可
我們把twic DataFrame的`'OPEN'` column取出來,另外存到twic_open這個新的變數裡。
```python=+
twic_open = twic['Open']
print(twic_open)
```
#### 使用iloc(位置呼叫)
我們也可以使用DataFrame的iloc來存取DataFrame裡面的資料。
iloc意思是 integer location(整數位置),就是把DataFrame裡面的窗格做編號,用`[列,行]`的順序存取。
記得,數數是從0開始。
```python=+
print(twic.iloc[12,4])
print(twic.iloc[:,4])
print(twic.iloc[12])
```
#### 切片 slice
你也可以用iloc來做切片,就如同前面對列表做的一樣。
```python=+
#最近五十天的開高低收
print(twic.iloc[0:50,1:5])
```
### Series
#### Series構成DataFrame
試著印出twic_open的type,會發現他是一個叫作Series(意為序列)的變數型態,你可以想像,就是這一行一行的Series組合成一個DataFrame。
```python=+
print(type(twic_open))
```
```python=+
twic['new_column'] = 0
print(twic)
```
#### 數學運算
相同長度的Series可以互相做運算,很常見的像是加減乘除。運算結果會得到一個新的Series。
程式碼->twic['漲跌'] 會在twic DataFrame中新增欄位,並取名為"漲跌"
```python=+
twic_open = twic['OPEN']
twic_close = tiwc['CLOSE']
twic['漲跌'] = twic_close - twic_open
twic['漲跌幅'] = (twic_close - twic_open) / twic_open
```
那請問如果我們將每日的收盤價減去開盤價,我們得到的這個新的series代表什麼意思?
Ans: 日K線的長度,負號代表黑K。
#### 成員函式
##### max, min, mean......
```python
print(twic_open.max())
print(twic_open.min())
print(twic_open.mean())
```
##### pct_change
拿來計算成長率
```python
print(twic_open.pct_change(periods=1))
print(twic_open.pct_change(periods=2))
```
## 3-3 DataFrame 操作
### 命名、更新
直接重新命名
```python=+
twic.columns = ['open','high','low','close','adj_close','volume']
print(twic)
```
也可以用DataFrame的rename方法。
```python=+
twic = pd.read_csv('2330twic.csv', index_col='Date')
twic = twic.rename(columns={'High': 'HIGH'})
print(twic.columns)
```
### 合併、插入、拼接
#### merge
- 下載數據
```python=+
import pandas_datareader as pdr
# 加權指數
twii = pdr.DataReader('^TWII','yahoo',start='2000')
# 0050台灣五十
price_0050 = pdr.DataReader('0050.TW','yahoo',start='2000')
```
- 合併數據
使用`index索引`合併請使用`left_index`=True
使用`column名稱`合併請使用`left_on`='xx'(ex:"Date")
```python=+
merged = pd.merge(twii, price_0050, left_index=True, right_on='Date')
print(merged.columns)
```
有名稱一樣的columns,pandas會自動的標上`_x,_y` 作為後綴。我們也可以自己設定。
```python=+
merged = pd.merge(twii, price_0050, left_on='Date', right_on='Date', suffixes = ('_twii','_0050'))
print(merged.columns)
```
#### append
往下append
```python=+
twii = pdr.DataReader('^TWII','yahoo')
```
`ignore_index·` : 重新排序index
`sort` : 對columns排序
```python=+
df1 = twii[:"2017"]
df2 = twii["2018":]
df1.append(df2, ignore_index=True, sort=False)
```
#### join
往右join
```python=+
joined = twii.join(price_0050,rsuffix='_0050')
```
#### shift
正數代表往下平移,負號代表往上平移
```python=+
twic.shift(1)
```
```python=+
twic.shift(-3)
```
也可以對Series做。
```python=+
twic_close.shift(1)
```
```python=+
twic_close - twic_close.shift(1)
```
這樣可以得到收盤價對前一天的漲跌
## 3-4 分組與滾動處理
### rolling
rolling是一個移動窗格的概念,將一個DataFrame的橫列N個作為一組。再來就可以接上我們想要的[操作](https://pandas.pydata.org/pandas-docs/stable/reference/window.html),最常用的max, min, mean等。
我們試試看用rolling().mean()來做移動平均線。
```python=+
close = twic['Close']
ma_5 = close.rolling(5).mean()
twic['CLOSE_MA_5D'] = ma_5
```
#### 破新高
```python=+
close = twic['Close']
# close = twic.Close
max_20 = close.rolling(20).max()
is_new_price = (max_20 == twic['ADJ_CLOSE'])
twic['IS_NEW_PRICE'] = is_new_price
```
### groupby
groupby可以以某個欄位或者Series進行分組,為了方便學習,我們使用for迴圈的方式進行拆解。
```python=+
twic.index = pd.to_datetime(twic.index)
groups = twic.groupby([twic.index.year, twic.index.month])
for group, frame_window in groups:
print(group)
print(frame_window)
print('open:', frame_window.iloc[0,0])
print('high:', frame_window['High'].max())
print('low:', frame_window['Low'].min())
print('close:', frame_window.iloc[-1,3])
```
更好、更快的方法
```python=+
twic.groupby([twic.index.year,twic.index.month])["Close"].ohlc()
```
## 3-5 apply
### apply
這個功能極為重要,請多試試
```python=+
def add2(x):
return x + 2
twic_open.apply(add2)
```
## 3-6 第二次作業
- 下載0056及0050資料
- 將兩資料的“調整日收盤價”轉成“月調整收盤價”資料
- 將兩資料轉成起始為100的權益並用plot函數畫出