2020年3月14日 星期六

被 genfromtxt 打敗

先前寫 python 程式時, 一直都用 自己手工打造的 csv 讀檔副程式; 但基於 「站在巨人肩膀上」 的理念, 仍舊希望改用別人寫好的現成函式庫。 剔除 速度超慢且有點難用的 pandas 之後, 發現 numpy 的 genfromtxt 貌似很好用。 (比 loadtxt 有更多彈性。) 結果在一個奇怪的 bug 卡好久 :-(

用 「太陽系天然衛星列表」 當測試資料好了: wget https://ckhung.github.io/a/m/18/satellites.csv 接著進入 python3 (或 python2) 的 interpreter。

import numpy as np
table = np.genfromtxt('satellites.csv', delimiter=',', autostrip=True, comments="#")
table

首先呢, 我很喜歡 genfromtxt 提供了略過註解列 (comments="#") 及自動去除每個欄位的頭尾空白字串 (autostrip=True) 等等功能。 但是上面的結果會得到很多 nan, 因為 genfromtxt 預設把所有欄位都當成數值。 沒關係, 呼叫時加上 dtype=str , 於是所有的欄位都變成字串了。 如果用 dtype=None , 則 genfromtxt 會自動猜測各欄位型態; dtype 也可以是一個 tuple (不是陣列!) 明確地個別設定每個欄位; 它的語法也可以很複雜 (簡中英文手冊英文手冊)。 不過那些都與今天的主題無關; 今天我們要談的問題, 用最簡單的 dtype=str 就會觸發; 改用其他複雜的組合也無濟於事。

問題是這樣的: 我們的 csv 檔有標題列, 所以可以加上 names=True 叫 genfromtxt 拿那一列來當欄位名稱。 結果一加上去就爆炸了: 讀進來的資料全部變成空字串~ 昏倒~ (請敲進 table.dtype 查看每個欄位的 dtype)。 搜尋很久, 一開始找錯方向, 很後來才發現: 原來很多人跟我有相同的困擾: 12更多。 最後終於發現 這是一個 open issue。 算了, 還是乖乖用自造的輪子好了。

沒有留言:

張貼留言