Pandas 格式處理、排序與篩選-Python 套件使用(三)

一、前言

恭喜各位來到第二篇 Pandas 囉!如果還不清楚什麼是 Pandas ,建議先看上一篇,了解基本使用方式。這邊讓大家繼續往下看更多更細的操作。跟著上一篇的格式,我們繼續沿用囉!

import pandas as pd
dic = {
    "date": ['2020/10/15', '2020/10/16', '2020/10/17', '2020/10/18', '2020/10/19',    '2020/10/20', '2020/10/21'],
    "open": [200, 300, 400, 500, 600, 700, 800],
    "close": [150, 250, 350, 450, 550, 650, 750],
}
df = pd.DataFrame(dic)
# 指定index
df = pd.DataFrame(dic, index=df['date'])


追蹤量化通的粉絲專頁量化通QuantPass」即時獲取實用的資源!

二、基礎資訊:

1. df.Info():

這功能會幫你把此表格的基本資訊吐給你,有興趣的朋友可以更深入研究看看:

# print(df.info())
<class 'pandas.core.frame.DataFrame'>
Index: 7 entries, 2020/10/15 to 2020/10/21
Data columns (total 3 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   date    7 non-null      object
 1   open    7 non-null      int64 
 2   close   7 non-null      int64 
dtypes: int64(2), object(1)
memory usage: 224.0+ bytes
None

2. df.describe():

可以得到一張能快速瀏覽相關內部數據的統計資料,大家可以根據個人的使用情境決定是否需要。

3.常見的四種模式:

(1)df.to_dict(‘dict’):

將 DataFrame 轉換為 index 為 key,內容各自對應順序為 key-value 的 dictionary 資料結構。

(2)df.to_dict(‘list’):

將 DataFrame 轉換為 column 為 key,整欄位為 list-value 的資料結構。

(3)df.to_dict(‘index’):

將 DataFrame 轉換為 index 為 key,該 row 為 list-value 的資料結構。

(4)df.values.tolist():

將 DataFrame 的 value 直接轉換為 list-list 的資料結構。

# 列出 DataFrame 的 index/columns
print(df.index)
print(df.columns)

# 表示將date資料轉移至index,下次呼叫value時,不會回傳 date,讓date成為key的概念。
df.set_index("date" , inplace=True)
print(df)

# 重製index,取代現在的index
df.reset_index(inplace=True) 
print(df)


# 以下四種操作要很熟悉
print(df.to_dict('dict')) 

print(df.to_dict('list'))  

print(df.to_dict('index'))  

print(df.values.tolist())  

結果很長,我們直接看:

# print(df.to_dict('dict'))  的結果
{'date': {0: '2020/10/15', 1: '2020/10/16', 2: '2020/10/17', 3: '2020/10/18', 4: '2020/10/19', 5: '2020/10/20', 6: '2020/10/21'}, 'open': {0: 200, 1: 300, 2: 400, 3: 500, 4: 600, 5: 700, 6: 800}, 'close': {0: 150, 1: 250, 2: 350, 3: 450, 4: 550, 5: 650, 6: 750}}

# print(df.to_dict('list')) 的結果
{'date': ['2020/10/15', '2020/10/16', '2020/10/17', '2020/10/18', '2020/10/19', '2020/10/20', '2020/10/21'], 'open': [200, 300, 400, 500, 600, 700, 800], 'close': [150, 250, 350, 450, 550, 650, 750]}

# print(df.to_dict('index'))   的結果
{0: {'date': '2020/10/15', 'open': 200, 'close': 150}, 1: {'date': '2020/10/16', 'open': 300, 'close': 250}, 2: {'date': '2020/10/17', 'open': 400, 'close': 350}, 3: {'date': '2020/10/18', 'open': 500, 'close': 450}, 4: {'date': '2020/10/19', 'open': 600, 'close': 550}, 5: {'date': '2020/10/20', 'open': 700, 'close': 650}, 6: {'date': '2020/10/21', 'open': 800, 'close': 750}}

# print(df.values.tolist()) 的結果
[['2020/10/15', 200, 150], ['2020/10/16', 300, 250], ['2020/10/17', 400, 350], ['2020/10/18', 500, 450], ['2020/10/19', 600, 550], ['2020/10/20', 700, 650], ['2020/10/21', 800, 750]]

範例中最後四種操作需要很熟練在運用上才會方便,在資料轉換上使用 pandas,可以將資料直接轉成想要的資料結構並且存成 csv,會大大加速資料處理整體的速度與操作步驟。

在這些操作後,任何資料都能轉成 DataFrame。 DataFrame 基本上能轉成任何種資料形式,所以只要熟悉操作 pandas,就能將 csv 當成資料儲存的位置,將爬蟲當成資料來源,所有資料處理、轉換、增刪改,都交給 pandas 操作即可,是不是非常方便呢!

Py 101209161710
Py 101209161711

三、Pandas DataFrame 的 4 種常見的操作:

前置資料如下:

import pandas as pd
dic = {
    "date": ['2020/10/15', '2020/10/16', '2020/10/17', '2020/10/18', '2020/10/19', '2020/10/20', '2020/10/21'],
    "open": [200, 300, 400, 500, 600, 700, 800],
    "close": [150, 250, 350, 450, 550, 650, 750],
}
df = pd.DataFrame(dic)
df = pd.DataFrame(dic, index=df['date'])
df.set_index("date", inplace=True)

print(df)

1. 新增/修改Pandas DataFrame資料

(1)df[‘colume_name’]:

df["high"]=[111, 222, 333, 444, 555, 666, 777]
print(df)

"""
結果:
           open  close  high
date                         
2020/10/15   200    150   111
2020/10/16   300    250   222
2020/10/17   400    350   333
2020/10/18   500    450   444
2020/10/19   600    550   555
2020/10/20   700    650   666
2020/10/21   800    750   777
"""

(2)df.insert:

使用 insert 的方式,針對某一列直接插入整欄資料,就如同 list 的操作方式一樣:

df.insert(0,"high",[111, 222, 333, 444, 555, 666, 777])
print(df)

"""
結果
           high  open  close
date                         
2020/10/15   111   200    150
2020/10/16   222   300    250
2020/10/17   333   400    350
2020/10/18   444   500    450
2020/10/19   555   600    550
2020/10/20   666   700    650
2020/10/21   777   800    750

"""

(3)df.append:

以 append 增加排(row)的方式新增資料,邏輯跟 list 類似。

df = df.append({'open': 158, 'close' : 168}, ignore_index=True)
print(df)

用「ignore_index=True」能將資料新增到最後,也會自動產出一個新的 index。

  open  close
0   200    150
1   300    250
2   400    350
3   500    450
4   600    550
5   700    650
6   800    750
7   158    168 #這邊,可是因為忽略index故又變回原本的順序了

(4)使用loc[n]針對順序插入row資料:

df.loc['2021/12/31'] = [456, 4567]
df.loc['2021/11/31'] = [789, 6789]
print(df)

"""
結果
           open  close
date                   
2020/10/15   200    150
2020/10/16   300    250
2020/10/17   400    350
2020/10/18   500    450
2020/10/19   600    550
2020/10/20   700    650
2020/10/21   800    750
2021/12/31   456   4567 # 資料會新增在特定位置
2021/11/31   789   6789 # 資料會新增在特定位置

"""

有沒有發現,前面幾種方式將資料變成 index,而後面將資料照順序填入 row,在這裡其實是取代的意思,如果這數值存在就取代它,如果不存在則新增一筆。

df.loc['2021/12/31'] = [456, 4567]
df.loc['2020/10/16'] = [789, 6789]
print(df)

"""
結果
           open  close
date                   
2020/10/15   200    150
2020/10/16   789   6789  # 原本存在會直接取代
2020/10/17   400    350
2020/10/18   500    450
2020/10/19   600    550
2020/10/20   700    650
2020/10/21   800    750
2021/12/31   456   4567 # 不存在的則會新增

"""

2.刪除Pandas DataFrame資料

# 使用 drop 指定欄位,記得要給定 axis=1 為欄。若 axis=0 為代表列
drop_col = df.drop(['open'], axis=1)
drop_row = df.drop(['2020/10/17'], axis=0)
print(drop_col)
print(drop_row)

結果:

           close
date             
2020/10/15    150
2020/10/16    250
2020/10/17    350
2020/10/18    450
2020/10/19    550
2020/10/20    650
2020/10/21    750
# 上面的 open colume 直接被 drop 掉。
# 底下的 2020/10/17 row 也是被刪掉。
            open  close
date                   
2020/10/15   200    150
2020/10/16   300    250
2020/10/18   500    450
2020/10/19   600    550
2020/10/20   700    650
2020/10/21   800    750

3. 篩選Pandas DataFrame資料

這小結會稍微難一點,因為針對取的 colume(縱向)或是 row(橫向)不同,那就可能會造成不同的取法與結果,也是一個需要熟練的部分,那主要會分成以下兩項:

(1)df.loc:

類似有順序的字典操作方式:

# loc指向的是index的名稱
print(df.loc["2020/10/19"]) #選 "2020/10/19" 的資料
print(df.loc["2020/10/18", ['open']]) # 選"2020/10/18" 的open資料
print(df.loc[:, ['open']] )# 選所有的open資料

第一個結果:可以看出第一個值就是先選 row 的 index 名稱。

第二個結果:表示選出指定的 row 之後,在針對該 row 去找對應的 colume,並取出那個欄位內的 value。

第三個結果:則是跳過第一個,直接取出 colume = “open” 的資料

# print(df.loc["2020/10/19"])
open     600
close    550
Name: 2020/10/19, dtype: int64

# print(df.loc["2020/10/18", ['open']])
open    500
Name: 2020/10/18, dtype: int64

# print(df.loc[:, ['open']] )
            open
date            
2020/10/15   200
2020/10/16   300
2020/10/17   400
2020/10/18   500
2020/10/19   600
2020/10/20   700
2020/10/21   800

(2)df.iloc:

「iloc」語法,是更偏向於順序與 list切片式的做法。

# iloc指向的是index的位置
print(df.iloc[3])        # 取出第四個 row
print(df.iloc[0:5, 0:1]) # 取出一個區塊 (row_idx=0, 1 and col_idx=0,1)
print(df.iloc[1:4, :])   # 根據row index選擇
print(df.iloc[:, 1:3])   # 根據column index選擇

從結果中可以看出基本上邏輯就跟list一樣,主要是第三、四個結果作法與 loc一樣,都是對列、欄位下條件,進而取出需要的範圍

注意這邊是範圍哦!跟上面的只取出指定資料不同,更像是在excel內用滑鼠框出一個區域的感覺,是不是很有感覺啊!

# print(df.iloc[3])    的結果
open     500
close    450
Name: 2020/10/18, dtype: int64

# print(df.iloc[0:5, 0:1])  的結果
            open
date            
2020/10/15   200
2020/10/16   300
2020/10/17   400
2020/10/18   500
2020/10/19   600

# print(df.iloc[1:4, :])   的結果
            open  close
date                   
2020/10/16   300    250
2020/10/17   400    350
2020/10/18   500    450

# print(df.iloc[:, 1:3])  的結果
            close
date             
2020/10/15    150
2020/10/16    250
2020/10/17    350
2020/10/18    450
2020/10/19    550
2020/10/20    650
2020/10/21    750

4.排序Pandas DataFrame資料

首先先將取得的資料整理一下,做基本的處理。

import pandas as pd
new_dic = {
    "date": ['2020/10/15', '2020/10/16', '2020/10/17', '2020/10/18', '2020/10/19', '2020/10/20', '2020/10/21'],
   "open": [112, 157, 185, 112, 157, 185, 112],
    "close": [250, 250, 250, 125, 125, 125, 50],
}
df = pd.DataFrame(new_dic)
df = pd.DataFrame(new_dic, index=df['date'])
df.set_index("date", inplace=True)

print(df)

"""
結果
           open  close
date                   
2020/10/15   112    250
2020/10/16   157    250
2020/10/17   185    250
2020/10/18   112    125
2020/10/19   157    125
2020/10/20   185    125
2020/10/21   112     50

"""

再來加入 sort 語法,排序 DataFrame 資料,這邊的邏輯就很像對表格做先後排序,跟電商網站選商品時,依照價格排序的感覺很像,都可以有先後順序的:

# 將open列的數據依照數值大小進行小至大的排序
sort_df = df.sort_values(['open'], ascending=True)
print(sort_df) 

# 將open、close列數據依照數值大小進行大至小排列
sort_df = df.sort_values(['open','close'], ascending=False)
print(sort_df) 

結果:

#  只針對open進行小到大的排列,但close不動
           open  close
date                   
2020/10/15   112    250
2020/10/18   112    125
2020/10/21   112     50
2020/10/16   157    250
2020/10/19   157    125
2020/10/17   185    250
2020/10/20   185    125

# 第二個用法通常用在同個open值中有不同的close,並進行排序
           open  close
date                   
2020/10/17   185    250
2020/10/20   185    125
2020/10/16   157    250
2020/10/19   157    125
2020/10/15   112    250
2020/10/18   112    125
2020/10/21   112     50

四、小結:

看到這邊是不是眼花撩亂啊!沒關係,這種各類操作本來就是得常做才會,這很正常的!那既然各位都堅持到這邊了,就讓我們加把勁完成它吧!

那一樣有任何心得或是想要討論,都歡迎底下留言哦!


量化通粉絲社群,一起討論程式交易!

加入LINE社群量化交易討論群」無壓力討論與分享!

加入臉書社團「程式交易 Taiwan」即時獲取實用的資源!

RoWay
RoWay

多年投資經驗的兩岸三地操盤手,曾任海外資產管理公司交易平台的產品經理、與各外商投資公司合作開發各式交易策略與系統。

擅長用Python執行資料蒐集、整理、分析與交易;也善於用Multicharts、MetaTrader等系統建構並回測期貨、期權、區塊鏈策略進而完成投資組合管理。

文章: 27

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *