目錄

在 Python 中使用 NumPy 進行檔案的讀取與寫入

封面圖片是 NumPy 的官方 Logo , 2025 年 2 月 26 日擷取自 Github 。

前言

提到 Python 中的數值、矩陣運算,我們不得不提受到大多數程式設計者歡迎的 NumPy 模組。 NumPy 支援高維度、大規模的多維陣列與矩陣運算,並針對陣列運算提供大量的數學函式函式庫,使得在 Python 中進行數值運算時更加快速與容易。較可惜的是 NumPy 只能在 CPU 運行,無法利用 GPU 加速運算。

本文僅介紹 NumPy 的檔案讀取與寫入,有關 NumPy 的其他功能請參考其他文章或參考官方文件 https://numpy.org/doc/stable/reference/

支援的檔案格式

NumPy 以二進制模式 (binary mode) 讀寫檔案,支援將資料寫入二進制格式檔案及純文字格式檔案。常見的格式有 NumPy 專用的二進制格式 .npy.npz ,二進制格式 .bin ,純文字格式檔案 .txt.csv 等。

.npy 格式

.npy 格式是用於儲存與載入 NumPy 的陣列類別 ndarray 的資料、形狀 (shape)、資料類型 (dtype) 等資訊。由於 .npy 檔案是單個數組儲存格式,因此只能儲存一個 NumPy 陣列。但因為 .npy 檔案採用二進制格式進行儲存,故比 .txt.csv 等格式更節省空間,讀取速度更快。

.npz 格式

.npz 格式與 .npy 格式具有相同功能。不同的是 .npz 格式可以用來儲存多個 NumPy 陣列,且可以使用 .savez_compressed() 將資料進行壓縮。

.bin 格式

.bin 格式雖然也是二進制格式,但與 .npy 格式不同的是,.bin 格式只儲存資料,不儲存資料的形狀及資料類型。因此,在讀取 .bin 格式時總是需要手動指定資料的形狀。

寫入檔案

NumPy 將數值、矩陣寫入檔案的語法有很多種,以下介紹 .save().savez().savez_compressed().savetxt().tofile() 等方法。

我們首先載入 NumPy 模組,並假設有兩 Numpy 陣列,分別為 arr1arr2

1
2
3
4
import numpy as np

arr1 = np.array([10, 20, 30])
arr2 = np.array([[1, 2], [3, 4]])

.save()

適用於:

  • 將單個陣列儲存為 NumPy 的 .npy 二進制格式。

用法:

.save(file, arr, allow_pickle=True)

參數:

  • file: 要儲存的檔案名稱、字串或檔案路徑。
  • arr: 要儲存的陣列。
  • allow_pickle: 布林值,可選填。允許使用 Python pickle 儲存物件陣列,但並非所有 pickle 資料都相容於不同版本的 Python。預設為 True

範例程式:

1
np.save("array.npy", arr1) # 儲存到 "array.npy" 檔案

.savez()

適用於:

  • 將多個陣列以未壓縮的格式儲存到 .npz 的單一檔案中。

用法:

.savez(file, *args, allow_pickle=True, **kwds)

參數:

  • file: 要儲存的檔案名稱、字串或檔案路徑。
  • args: 要儲存的陣列,可選填。請使用下方的 kwds 為每個陣列指定名稱,若使用 args 儲存陣列,則預設名稱為 "arr_0""arr_1" 等等。
  • allow_pickle: 布林值,可選填。允許使用 Python pickle 儲存物件陣列,但並非所有 pickle 資料都相容於不同版本的 Python。預設為 True
  • kwds: 要儲存的陣列,可選填。每個陣列將與其對應的自定義名稱一起儲存到輸出的檔案中。

範例程式:

1
np.savez("arrays.npz", first=arr1, second=arr2) # 儲存多個陣列

.savez_compressed()

適用於:

  • 將多個陣列以壓縮的格式儲存到 .npz 的單一檔案中。

用法:

.savez_compressed(file, *args, allow_pickle=True, **kwds)

參數:

  • file: 要儲存的檔案名稱、字串或檔案路徑。
  • args: 要儲存的陣列,可選填。請使用下方的 kwds 為每個陣列指定名稱,若使用 args 儲存陣列,則預設名稱為 "arr_0""arr_1" 等等。
  • allow_pickle: 布林值,可選填。允許使用 Python pickle 儲存物件陣列,但並非所有 pickle 資料都相容於不同版本的 Python。預設為 True
  • kwds: 要儲存的陣列,可選填。每個陣列將與其對應的自定義名稱一起儲存到輸出的檔案中。

範例程式:

1
np.savez_compressed("arrays_compressed.npz", first=arr1, second=arr2)

.savetxt()

適用於:

  • 將陣列儲存為純文字檔案 (.txt.csv) 。

用法:

.savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='\n', header='', footer='', comments='# ', encoding=None)

參數:

  • fname: 要儲存的檔案名稱、字串或檔案路徑。如果副檔名為 .gz ,則將自動儲存為 gzip 壓縮格式, .loadtxt() 也會自動解壓縮讀取 gzip 壓縮檔案。
  • X: 要儲存到純文字檔案的一維或二維陣列。
  • fmt: 字串或字串序列,可選填。此參數較複雜,請參考原始文件 https://numpy.org/doc/stable/reference/generated/numpy.savetxt.html
  • delimiter: 資料間的分隔符號,用於分隔每一列。可為字串或字元,可選填。
  • newline: 換行符號,用於分隔每一行。可為字串或字元,可選填。
  • header: 寫在檔案開頭的字串。
  • footer: 寫在檔案末端的字串。
  • comments: 寫在 headerfooter 前的註解符號,預設為 "# "
  • encoding: None 或字串,可選填。 NumPy 對輸出的檔案編碼進行的編碼,預設為 "latin1"

範例程式:

1
np.savetxt("array.txt", arr1, delimiter=",")

.tofile()

適用於:

  • 以二進制或純文字格式儲存,預設為二進制格式。

用法:

.tofile(fid, sep='', format='%s')

參數:

  • fid: 要儲存的檔案名稱、字串或檔案路徑。
  • sep: 字串,資料間的分隔符號。
  • format: 字串,文字檔案輸出的格式字串。

範例程式:

1
2
arr1.tofile("array.bin") # 預設為二進制格式
arr2.tofile("array.txt", sep=",", format="%d") # 以純文字格式儲存

讀取檔案

以下介紹使用 .load().loadtxt().genfromtxt().fromregex().fromstring().fromfile() 等方法將檔案讀取到 NumPy 中。

我們首先載入 NumPy 模組。

1
import numpy as np

.load()

適用於:

  • .npy.npz 或 pickle 檔案讀取陣列或 pickle 物件。

用法:

.load(file, mmap_mode=None, allow_pickle=False, fix_imports=True, encoding='ASCII', *, max_header_size=10000)

參數:

  • file: 要讀取的檔案名稱、字串或檔案路徑。
  • mmap_mode: Noner+rw+c ,可選填。此參數較複雜,請參考原始文件 https://numpy.org/doc/stable/reference/generated/numpy.load.html
  • allow_pickle: 布林值,可選填。是否允許載入儲存在 .npy 檔案中的 pickle 物件陣列。預設為 False
  • fix_imports: 布林值,可選填。僅在 Python 3 上載入 Python 2 產生的 pickle 檔案時有用。
  • encoding: "latin1""ASCII""bytes",可選填。讀取 Python 2 字串時使用的編碼,預設 "ASCII"
  • max_header_size: 整數,可選填。允許的最大 header 大小。較大的 header 可能不安全,導致無法安全載入。

範例程式:

1
2
3
4
5
loaded_arr = np.load("array.npy") # 讀取 `.npy`
print(loaded_arr)

loaded_npz = np.load("arrays.npz") # 讀取 `.npz`
print(loaded_npz["first"]) # 讀取 `arrays.npz` 中的 "first" 陣列

.loadtxt()

適用於:

  • 讀取純文字檔案。

用法:

.loadtxt(fname, dtype=<class 'float'>, comments='#', delimiter=None, converters=None, skiprows=0, usecols=None, unpack=False, ndmin=0, encoding=None, max_rows=None, *, quotechar=None, like=None)

參數:

  • fname: 要讀取的檔案名稱、字串、檔案路徑或生成器 (generator) 。如果副檔名為 .gz ,會自動解壓縮讀取 gzip 壓縮檔案。
  • dtype: 資料類型,可選填。預設為 float
  • comments: 註解符號,字串或 None ,可選填。預設為 "# "
  • delimiter: 分隔符號,字串,可選填。預設為空格。
  • converters: 字典 (dict) ,可選填。預設為 None
  • skiprows: 跳過前 skiprows 行,包括註解。預設為 0 。
  • usecols: 要讀取哪些列,整數,可選填。 0 表示第一列,以此類推。預設為 None ,表示讀取所有欄位。
  • unpack: 布林值,可選填。為 True 時傳回的陣列將被轉置。預設為 False
  • ndmin: 整數,可選填。陣列至少有 ndmin 個維度,有效值為 0(預設)、 1 或 2 。
  • encoding: 字串,可選填。預設為 None 。此參數較複雜,請參考原始文件 https://numpy.org/doc/stable/reference/generated/numpy.loadtxt.html
  • max_rows: 整數,可選填。在 skiprows 行之後讀取 max_rows 行的內容,但不包含空行。
  • quotechar: unicode 字元或 None ,可選填。引用項目的開始和結束的字元,預設為 None
  • like: array_like 類別,可選填。建議參考原始文件 https://numpy.org/doc/stable/reference/generated/numpy.loadtxt.html

範例程式:

1
2
loaded_txt = np.loadtxt("array.txt", delimiter=",", dtype=int)
print(loaded_txt)

.genfromtxt()

適用於:

  • 從純文字檔案載入資料,並以指定方式處理缺失值。

用法:

.genfromtxt(fname, dtype=<class 'float'>, comments='#', delimiter=None, skip_header=0, skip_footer=0, converters=None, missing_values=None, filling_values=None, usecols=None, names=None, excludelist=None, deletechars=" !#$%&'()*+, -./:;<=>?@[\\]^{|}~", replace_space='_', autostrip=False, case_sensitive=True, defaultfmt='f%i', unpack=None, usemask=False, loose=True, invalid_raise=True, max_rows=None, encoding=None, *, ndmin=0, like=None)

參數:

  • fname: 要讀取的檔案名稱、字串、檔案路徑或生成器 (generator) 。如果副檔名為 .gz.bz2 ,會自動解壓縮讀取該壓縮檔案。
  • dtype: 資料類型,可選填。預設為 float
  • comment: 註解符號,字串,可選填。
  • delimiter: 分隔符號,字串、整數或序列,可選填。
  • skip_header: 整數,可選填。檔案開頭要跳過的行數。
  • skip_footer: 整數,可選填。檔案末端要跳過的行數。
  • converters: 變數,可選填。將列的資料轉換為值的一組函數,也可為缺失資料提供預設值。
  • missing_values: 變數,可選填。對應到缺失資料的字串。
  • filling_values: 變數,可選填。缺失資料的預設值。
  • usecols: 要讀取哪些列,整數,可選填。 0 表示第一列,以此類推。預設為 None ,表示讀取所有欄位。
  • names: NoneTrue 、字串或序列,可選填。如果為 True ,將從 skip_header 行之後的第一行讀取欄位名稱。
  • excludelist: 序列,可選填。要從 names 排除的的清單。
  • deletechars: 字串,可選填。定義要從 names 中刪除的無效字元清單。
  • replace_space: 字元,可選填。替換變數名稱中空格的字元,預設為 "_"
  • autostrip: 布林值,可選填。是否自動從變數中去除空格。
  • case_sensitive: TrueFalse"upper""lower" ,可選填。如果為 True,則欄位名稱區分大小寫。如果為 False"upper" ,則欄位名稱將轉換為大寫。如果為 "lower" ,則欄位名稱將轉換為小寫。
  • defaultfmt: 字串,可選填。定義預設欄位名稱的格式。
  • unpack: 布林值,可選填。為 True 時傳回的陣列將被轉置。預設為 False
  • usemask: 布林值,可選填。為 True 時,回傳一個 masked 陣列。為 False 時,則回傳一個 regular 陣列。
  • loose: 布林值,可選填。為 True 時,不會因無效值而引發錯誤。
  • invalid_raise: 布林值,可選填。為 True 時,偵測到列數不一致時會引發異常。為 False 時,會發出警告並跳過有問題的行。
  • max_rows: 整數,可選填。要讀取的最大行數,不能與 skip_footer 同時使用,且值必須至少為 1。
  • encoding: 字串,可選填。用於解碼輸入檔案的編碼,預設為 None
  • ndmin: 整數,可選填。陣列至少有 ndmin 個維度,有效值為 0(預設)、 1 或 2 。
  • like: array_like 類別,可選填。建議參考原始文件 https://numpy.org/doc/stable/reference/generated/numpy.genfromtxt.html

範例程式:

1
2
loaded_gen = np.genfromtxt("array.txt", delimiter=",", dtype=int, filling_values=-1)
print(loaded_gen)

.fromregex()

適用於:

  • 從符合正則表達式的純文字檔案讀取陣列。

用法:

.fromregex(file, regexp, dtype, encoding=None)

參數:

  • file: 要讀取的檔案名稱、字串或檔案路徑。
  • regexp: 字串或或 regexp ,用於解析檔案的正則表達式。
  • dtype: 資料類型 (dtype) 或資料類型的列表。
  • encoding: 字串,可選填。用於解碼輸入檔案的編碼。

範例程式:

1
2
3
4
5
import io
data = io.StringIO("123 abc\n456 def\n789 ghi")
pattern = r"(\d+)\s(\w+)"  # 解析 "數字 + 空格 + 文字"
loaded_regex = np.fromregex(data, pattern, dtype=[("num", int), ("text", "U10")])
print(loaded_regex)

.fromstring()

適用於:

  • 從字串中的文字資料初始化為一個新的陣列。

用法:

.fromstring(string, dtype=float, count=-1, *, sep, like=None)

參數:

  • string: 包含資料的字串。
  • dtype: 資料類型,可選填。預設為 float
  • count: 整數,可選填。從 string 中讀取 count 個元素。如果 count 為負數,將讀取整個 string
  • sep: 分隔符號,字串,可選填。
  • like: array_like 類別,可選填。建議參考原始文件 https://numpy.org/doc/stable/reference/generated/numpy.fromstring.html

範例程式:

1
2
3
s = "1,2,3,4,5"
loaded_str = np.fromstring(s, dtype=int, sep=",")
print(loaded_str)

.fromfile()

適用於:

  • 從純文字檔案或二進制格式檔案中的資料建立陣列。

用法:

.fromfile(file, dtype=float, count=-1, sep='', offset=0, *, like=None)

參數:

  • file: 要讀取的檔案名稱、字串或檔案路徑。
  • dtype: 資料類型,可選填。
  • count: 要讀取的數量, -1 表示全部。
  • sep: 分隔符號,如果為純文字檔案,為 ""
  • offset: 整數。相對於檔案目前位置的偏移量,預設為 0 。
  • like: array_like 類別,可選填。建議參考原始文件 https://numpy.org/doc/stable/reference/generated/numpy.fromfile.html

範例程式:

1
2
3
4
5
loaded_bin = np.fromfile("array.bin", dtype=int)  # 讀取二進制資料
print(loaded_bin)

loaded_txt = np.fromfile("array.txt", dtype=int, sep=",")  # 讀取純文本資料
print(loaded_txt)

結語

想要徹底了解 NumPy 的輸入與輸出是一項大工程,這裡面也不乏許多我看不懂或根本沒用過的指令、參數。透過學習上述的指令,我想,我應該對於 NumPy 有著多一點的認識了吧?

參考資料