讀取和寫入檔案#

本頁處理常見應用;如需完整的 I/O 常式集合,請參閱輸入和輸出

讀取文字和 CSV 檔案#

無遺失值#

使用 numpy.loadtxt

有遺失值#

使用 numpy.genfromtxt

numpy.genfromtxt 將會

  • 返回一個 遮罩陣列 遮罩遺失值(如果 usemask=True),或

  • 填入遺失值,使用 filling_values 中指定的值(預設值為浮點數的 np.nan,整數的 -1)。

使用非空白字元分隔符#

>>> with open("csv.txt", "r") as f:
...     print(f.read())
1, 2, 3
4,, 6
7, 8, 9
遮罩陣列輸出#
>>> np.genfromtxt("csv.txt", delimiter=",", usemask=True)
masked_array(
  data=[[1.0, 2.0, 3.0],
        [4.0, --, 6.0],
        [7.0, 8.0, 9.0]],
  mask=[[False, False, False],
        [False,  True, False],
        [False, False, False]],
  fill_value=1e+20)
陣列輸出#
>>> np.genfromtxt("csv.txt", delimiter=",")
array([[ 1.,  2.,  3.],
       [ 4., nan,  6.],
       [ 7.,  8.,  9.]])
陣列輸出,指定填入值#
>>> np.genfromtxt("csv.txt", delimiter=",", dtype=np.int8, filling_values=99)
array([[ 1,  2,  3],
       [ 4, 99,  6],
       [ 7,  8,  9]], dtype=int8)

空白字元分隔#

numpy.genfromtxt 也可以解析具有遺失值的空白字元分隔資料檔案,如果

  • 每個欄位都有固定寬度:使用寬度作為 delimiter 參數。

    # File with width=4. The data does not have to be justified (for example,
    # the 2 in row 1), the last column can be less than width (for example, the 6
    # in row 2), and no delimiting character is required (for instance 8888 and 9
    # in row 3)
    
    >>> with open("fixedwidth.txt", "r") as f:
    ...    data = (f.read())
    >>> print(data)
    1   2      3
    44      6
    7   88889
    
    # Showing spaces as ^
    >>> print(data.replace(" ","^"))
    1^^^2^^^^^^3
    44^^^^^^6
    7^^^88889
    
    >>> np.genfromtxt("fixedwidth.txt", delimiter=4)
    array([[1.000e+00, 2.000e+00, 3.000e+00],
           [4.400e+01,       nan, 6.000e+00],
           [7.000e+00, 8.888e+03, 9.000e+00]])
    
  • 特殊值(例如 “x”)表示遺失欄位:將其用作 missing_values 參數。

    >>> with open("nan.txt", "r") as f:
    ...     print(f.read())
    1 2 3
    44 x 6
    7  8888 9
    
    >>> np.genfromtxt("nan.txt", missing_values="x")
    array([[1.000e+00, 2.000e+00, 3.000e+00],
           [4.400e+01,       nan, 6.000e+00],
           [7.000e+00, 8.888e+03, 9.000e+00]])
    
  • 您想要跳過具有遺失值的列:設定 invalid_raise=False

    >>> with open("skip.txt", "r") as f:
    ...     print(f.read())
    1 2   3
    44    6
    7 888 9
    
    >>> np.genfromtxt("skip.txt", invalid_raise=False)  
    __main__:1: ConversionWarning: Some errors were detected !
        Line #2 (got 2 columns instead of 3)
    array([[  1.,   2.,   3.],
           [  7., 888.,   9.]])
    
  • 分隔符空白字元與表示遺失資料的空白字元不同。 例如,如果欄位以 \t 分隔,則如果遺失資料由一個或多個空格組成,則會被識別出來。

    >>> with open("tabs.txt", "r") as f:
    ...    data = (f.read())
    >>> print(data)
    1       2       3
    44              6
    7       888     9
    
    # Tabs vs. spaces
    >>> print(data.replace("\t","^"))
    1^2^3
    44^ ^6
    7^888^9
    
    >>> np.genfromtxt("tabs.txt", delimiter="\t", missing_values=" +")
    array([[  1.,   2.,   3.],
           [ 44.,  nan,   6.],
           [  7., 888.,   9.]])
    

讀取 .npy 或 .npz 格式的檔案#

選擇

寫入檔案以供 NumPy 讀回#

二進位#

使用 numpy.save,或儲存多個陣列,使用 numpy.saveznumpy.savez_compressed

為了 安全性和可攜性,設定 allow_pickle=False,除非 dtype 包含 Python 物件,這需要 pickle 處理。

遮罩陣列 目前無法儲存,其他任意陣列子類別也無法儲存。

人類可讀#

numpy.savenumpy.savez 建立二進位檔案。 若要寫入人類可讀的檔案,請使用 numpy.savetxt。 陣列只能是一維或二維,並且沒有適用於多個檔案的 ` savetxtz`。

大型陣列#

請參閱 寫入或讀取大型陣列

讀取任意格式的二進位檔案(“二進位 blob”)#

使用 結構化陣列

範例

.wav 檔案標頭是一個 44 位元組的區塊,位於實際聲音資料的 data_size 位元組之前

chunk_id         "RIFF"
chunk_size       4-byte unsigned little-endian integer
format           "WAVE"
fmt_id           "fmt "
fmt_size         4-byte unsigned little-endian integer
audio_fmt        2-byte unsigned little-endian integer
num_channels     2-byte unsigned little-endian integer
sample_rate      4-byte unsigned little-endian integer
byte_rate        4-byte unsigned little-endian integer
block_align      2-byte unsigned little-endian integer
bits_per_sample  2-byte unsigned little-endian integer
data_id          "data"
data_size        4-byte unsigned little-endian integer

作為 NumPy 結構化 dtype 的 .wav 檔案標頭

wav_header_dtype = np.dtype([
    ("chunk_id", (bytes, 4)), # flexible-sized scalar type, item size 4
    ("chunk_size", "<u4"),    # little-endian unsigned 32-bit integer
    ("format", "S4"),         # 4-byte string, alternate spelling of (bytes, 4)
    ("fmt_id", "S4"),
    ("fmt_size", "<u4"),
    ("audio_fmt", "<u2"),     #
    ("num_channels", "<u2"),  # .. more of the same ...
    ("sample_rate", "<u4"),   #
    ("byte_rate", "<u4"),
    ("block_align", "<u2"),
    ("bits_per_sample", "<u2"),
    ("data_id", "S4"),
    ("data_size", "<u4"),
    #
    # the sound data itself cannot be represented here:
    # it does not have a fixed size
])

header = np.fromfile(f, dtype=wave_header_dtype, count=1)[0]

.wav 範例僅供說明;若要在實際情況中讀取 .wav 檔案,請使用 Python 的內建模組 wave

(改編自 Pauli Virtanen,Advanced NumPy,根據 CC BY 4.0 授權。)

寫入或讀取大型陣列#

太大而無法放入記憶體的陣列可以使用記憶體映射像普通記憶體內陣列一樣處理。

  • 使用 numpy.ndarray.tofilenumpy.ndarray.tobytes 寫入的原始陣列資料可以使用 numpy.memmap 讀取

    array = numpy.memmap("mydata/myarray.arr", mode="r", dtype=np.int16, shape=(1024, 1024))
    
  • numpy.save 輸出的檔案(即使用 numpy 格式)可以使用 numpy.loadmmap_mode 關鍵字引數讀取

    large_array[some_slice] = np.load("path/to/small_array", mmap_mode="r")
    

記憶體映射缺少資料分塊和壓縮等功能;與 NumPy 一起使用的更完整格式和函式庫包括

如需 memmap、Zarr 和 HDF5 之間的權衡,請參閱 pythonspeed.com

寫入檔案以供其他(非 NumPy)工具讀取#

用於交換資料與其他工具的格式包括 HDF5、Zarr 和 NetCDF(請參閱 寫入或讀取大型陣列)。

寫入或讀取 JSON 檔案#

NumPy 陣列和大多數 NumPy 純量並非直接 JSON 可序列化。 請改用自訂的 json.JSONEncoder 用於 NumPy 類型,可以使用您最愛的搜尋引擎找到。

使用 pickle 檔案儲存/還原#

盡可能避免使用; pickle 對於錯誤或惡意建構的資料並不安全。

使用 numpy.savenumpy.load。 設定 allow_pickle=False,除非陣列 dtype 包含 Python 物件,在這種情況下需要 pickle 處理。

numpy.loadpickle 子模組也支援 unpickling 使用 NumPy 1.26 建立的檔案。

從 pandas DataFrame 轉換為 NumPy 陣列#

請參閱 pandas.Series.to_numpy

使用 tofilefromfile 儲存/還原#

一般來說,偏好使用 numpy.savenumpy.load

numpy.ndarray.tofilenumpy.fromfile 會遺失關於位元組序和精確度的資訊,因此僅適用於臨時儲存。