# 輕鬆學會程式交易 | 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函數畫出