Pandas 填充空值、各類格式轉換與輸出-Python 套件使用(四)

恭喜各位撐到這章節,這章節會稍微輕鬆一些,比較偏理論的理解,就讓我們馬上開始吧!


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

一、填充/處理 NaN/NA 值:

很多人可能會很好奇,這個操作的功能是什麼呢?在資料處理的過程中,很常會遇到資料不見、缺失、異常等情形。當有資料缺失就難以分析,因此需要先處理有問題的資料,才有辦法分析。

以下會用到「numpy」套件,一樣我們先透過 Pycharm 左下方的 Terminal pip install numpy。

「numpy」是 Python 中對於資料處理更講求效能的套件,也相對更難,因此在這部分用到的功能只是產生 NaN,並不是「numpy」套件的操作方式。

先創建一份資料,並轉成 DataFrame:

import pandas as pd
import numpy as np

df = pd.DataFrame(
    [
        [np.nan, 2, np.nan, 0],
        [3, 4, 6, 1],
        [np.nan, np.nan, np.nan, 5],
        [np.nan, 3, np.nan, 4]
    ],
    columns=list('ABCD')
)

print(df)

邏輯上是先填補缺失值,再使用某些方式填進數值。以下會示範幾種方式,不表示這是最正確的做法。

各種資料填補方式與需求都不一樣,有些缺漏的資料缺了就是缺了,不應該被填補,因此應該根據每項資料與需求,決定如何填充與處理缺漏資料。

# 刪掉 NaN的對應的 colume、row,只留下資料完整的表格
clean = df.dropna()
print(clean)

# 以0填補
nadf = df.fillna(0)
print(nadf)

#以-999填補
df99 = df.fillna(-999)
print(df99)

# 以該欄位所有資料的算術平均數做填補
mean_df = df.fillna(df.A.mean())
print(mean_df)

#以該欄位所有資料的中位數做填補
med = df.fillna(df.median())
print(med)

直接看結果比較清楚喔!

# df.dropna() 的結果
     A    B    C  D
1  3.0  4.0  6.0  1

# df.fillna(0) 的結果
     A    B    C  D
0  0.0  2.0  0.0  0
1  3.0  4.0  6.0  1
2  0.0  0.0  0.0  5
3  0.0  3.0  0.0  4

#   df.fillna(-999) 的結果
       A      B      C  D
0 -999.0    2.0 -999.0  0
1    3.0    4.0    6.0  1
2 -999.0 -999.0 -999.0  5
3 -999.0    3.0 -999.0  4

# df.fillna(df.A.mean()) 的結果
     A    B    C  D
0  3.0  2.0  3.0  0
1  3.0  4.0  6.0  1
2  3.0  3.0  3.0  5
3  3.0  3.0  3.0  4

# df.fillna(df.median()) 的結果
     A    B    C  D
0  3.0  2.0  6.0  0
1  3.0  4.0  6.0  1
2  3.0  3.0  6.0  5
3  3.0  3.0  6.0  4

整理 DataFrame 的方法有很多,包含新增、修改、取得、刪除、篩選和排序資料等,最常見的使用方法有很多程式都能做到,但 pandas 的功能非常多,隨著使用情境的不同,功能也會不一樣,

因此藉由整理 DataFrame,帶大家熟練 Python 常見的功能、套件、語法與基本使用情境。

Py 101209161710
Py 101209161711

二、格式轉換:

1. datetime(字串) 轉換成 datetime (時間格式):

首先先上個假設的數據,Datetime 可以看出來是字串格式(有那個 _ 表示字串)。

df = pd.DataFrame(
    {
        'data1': [1, 2, 3],
        'data2': [4, 5, 6],
        'Datetime': ['2022/06/04_04:54:28', '2022/06/03_04:54:28', '2022/06/02_04:54:28'],
    }, index=['A', 'B', 'C']
)

這種在很多爬蟲的資料中都是長成各類字串格式的時間,所以讓 pandas 統一處理即可:

df['Datetime'] = pd.to_datetime(df['Datetime'], format="%Y/%m/%d_%H:%M:%S") # 處理有  "_" 的字串
# 結果
   data1  data2            Datetime
A      1      4 2022-06-04 04:45:00
B      2      5 2022-06-03 04:45:00
C      3      6 2022-06-02 04:45:00

有個更快速的方法,在數據量大的時候可以使用,速度大概差 60% 以上:

df['Datetime'] = df['Datetime'].apply(lambda index: datetime.strptime(index,"%Y/%m/%d_%H:%M:%S"))

此做法甚至比原先內建套件的還快上許多,但程式碼就相對難理解一點,就看情境的取捨囉!

2. 數據轉換:

先產一份簡易的隨機數據:

import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.rand(8, 4) * 5)
print(df)
"""
結果:
          0         1         2         3
0  0.434992  1.735385  1.824147  2.596633
1  0.960645  1.693874  3.945142  3.782143
2  2.820359  3.641548  2.414748  2.421735
3  0.373806  1.950452  3.706840  3.570724
4  2.340742  4.951858  1.253499  1.179138
5  0.839368  1.956993  1.279751  0.020432
6  4.838943  1.721855  4.860754  1.813471
7  3.478803  1.774799  2.179204  1.000244
"""

這類情境在爬蟲時也很常遇到,很多表格以為是數據,結果做完發現他是字串,但有時候是整份 csv 直接爬下來,不太適合邊爬邊處理數據時,不如就用這功能直接做轉換吧!

print(df.astype(int))
"""
結果:
   0  1  2  3
0  0  4  1  0
1  1  1  2  2
2  2  4  3  3
3  3  1  4  0
4  3  1  2  0
5  2  3  2  3
6  2  2  1  4
7  4  1  4  3
"""

可是雖然轉成了int,但其實直接轉成整數的話,會失去一些操作的空間,這時候就可以進階的使用 round 做四捨五入囉,當然,可以轉成 int 當然就可以轉回來囉:

# 用四捨五入正式處理一下數據
print(df.astype(int))

print("==============")
# 轉回來
new_df = df.astype(int)
print(new_df.astype(float))

馬上看一下結果:

   0  1  2  3
0  0  2  1  0
1  0  1  2  3
2  1  2  0  1
3  1  2  2  2
4  1  3  4  3
5  0  1  3  3
6  3  2  2  1
7  1  3  2  1
==============
     0    1    2    3
0  0.0  2.0  1.0  0.0
1  0.0  1.0  2.0  3.0
2  1.0  2.0  0.0  1.0
3  1.0  2.0  2.0  2.0
4  1.0  3.0  4.0  3.0
5  0.0  1.0  3.0  3.0
6  3.0  2.0  2.0  1.0
7  1.0  3.0  2.0  1.0

三、輸出:

一般而言,最常用的輸出格式便是 csv,可是針對其輸出方式也有一些常用的調整參數。使用上面的new_df當成輸出數據:

# 最簡易的輸出方式
new_df.to_csv("test_doc_1.csv")

# 可以選擇不要把 index 寫入csv
new_df.to_csv("test_doc_2.csv", index=False)

# DataFrame 寫入 CSV 時,預設是用逗號分隔。但如果某些條件下導致我們不能用逗號,則可以使用 sep 參數指定分隔符號。
new_df.to_csv("test_doc_3.csv", index=False, sep="\t")

結果便會有三份 csv囉,我們終於大功告成啦!

基本上這邊比較偏向於情境理解與基本操作,下一章節就是最後一章囉!大家加油!

如果有任何想要討論的,都歡迎底下留言!


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

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

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

RoWay
RoWay

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

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

文章: 27

發佈留言

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