Shopping Cart

購物車內沒有任何商品。

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'])

立即訂閱電子報,掌握最新資訊!

    稱呼

    電子郵件

    以下非必填,但若您願意分享,我們將能推送更精準的內容給您

    投資經驗

    是否為理工科背景、工程師或有寫程式的經驗?

    有興趣的主題
    量化交易台股期貨海外期貨虛擬貨幣美股

    有興趣的量化交易軟體/平台
    不清楚MultiChartsTradingViewPythonXQ

    想透過量化交易達成甚麼目的?
    不確定自動交易選股回測投資績效量化自己的投資方法想找現成的策略套用

    還有什麼想詢問的?

    2024tv黑五 1920 X 400 像素(pc端的banner)
    2024tv黑五 978 X 258(移動端的banner)


    二、基礎資訊:

    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社群量化交易討論群」無壓力討論與分享!

    加入Discord 「量化交易討論群」即時獲取實用的資源!

    Write Together 101306261122
    Write Together 101306261121
    RoWay
    RoWay

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

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

    文章: 28

    發佈留言

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