我正在嘗試使用 Numpy 對操作進行矢量化,以決議包含數字行的文本檔案并將資料轉換為 numpy 陣列。文本檔案中的資料如下所示:
*** .txt file ***
1 0 0 0 0
2 1 0 0 0
3 1 1 0 0
4 0 1 0 0
5 0 0 1 0
6 1 0 1 0
7 1 1 1 0
8 0 1 1 0
9 0.5 0.5 0 0
10 0.5 0.5 1 0
11 0.5 0 0.5 0
12 1 0.5 0.5 0
13 0.5 1 0.5 0
14 0 0.5 0.5 0
*** /.txt file ***
我的方法是讀取 using 中的行file.readlines(),然后將該行字串串列轉換為 numpy 陣列,如下所示 -file.readlines()部分省略以進行測驗。
short_list = ['1 0 0 0 0\n',
'2 1 0 0 0\n',
'3 1 1 0 0\n']
long_list = ['1 0 0 0 0\n',
'2 1 0 0 0\n',
'3 1 1 0 0\n',
'4 0 1 0 0\n',
'5 0 0 1 0\n',
'6 1 0 1 0\n',
'7 1 1 1 0\n',
'8 0 1 1 0\n',
'9 0.5 0.5 0 0\n',
'10 0.5 0.5 1 0\n',
'11 0.5 0 0.5 0\n',
'12 1 0.5 0.5 0\n',
'13 0.5 1 0.5 0\n',
'14 0 0.5 0.5 0\n']
def lines_to_npy(lines):
n_lines = len(lines)
lines_array = np.array(lines).astype('S')
tmp = lines_array.tobytes().decode('ascii')
print(repr(tmp))
print(lines_array.dtype)
print(np.array(tmp.split(), dtype=np.int32).reshape(n_lines, -1))
lines_to_npy(short_list)
lines_to_npy(long_list)
呼叫該函式short_list會產生以下輸出:
'1 0 0 0 0\n2 1 0 0 0\n3 1 1 0 0\n'
|S10
[[1 0 0 0 0]
[2 1 0 0 0]
[3 1 1 0 0]]
這是期望的結果(通過閱讀我收集到“|S10”意味著陣列中的每個元素都是一個 10 個字符的字串,位元組順序無關緊要)。但是,使用長串列呼叫會\x00在每個字串的末尾插入幾個空字符,這使得決議變得更加困難。
'1 0 0 0 0\n\x00\x00\x00\x00\x002 1 0 0 0\n\x00\x00\x00\x00\x003 1 1 0 0\n\x00\x00\x00\x00\x004 0 1 0 0\n\x00\x00\x00\x00\x005 0 0 1 0\n\x00\x00\x00\x00\x006 1 0 1 0\n\x00\x00\x00\x00\x007 1 1 1 0\n\x00\x00\x00\x00\x008 0 1 1 0\n\x00\x00\x00\x00\x009 0.5 0.5 0 0\n\x0010 0.5 0.5 1 0\n11 0.5 0 0.5 0\n12 1 0.5 0.5 0\n13 0.5 1 0.5 0\n14 0 0.5 0.5 0\n'
|S15
Note that an error was raised in my function when loading the null characters into an array, preventing a final result. I know that a "cheap and dirty" solution would be to just strip the null characters off the end. I also know that I could use Pandas to accomplish the main goal, too, but I'd like to understand why this behavior is occurring.
The \x00 are padded at the end of each string to make each string of length 15. This kind of makes sense, because the dtype of the short array was |S10, and each string just happened to be 10 characters long. The long array contains 14 strings, the dtype was |S15, and extra \x00 are appended to make the length of each item in the array 15 characters.
I am confused because the number of elements in the list of strings (3 vs 14) has no correlation to the length of each string, so I don't understand why the dtype changes to |S15 when adding more list elements.
Update: I did some more research on ways to efficiently read in data from a text file to a numpy array. I need a fast method for doing this because I am reading files with ~10M lines. numpy.loadfromtxt() and numpy.genfromtxt() are candidate solutions, but they are very slow because they are implemented in Python and basically do the same thing as manually looping through file.readlines(), stripping, and splitting the line strings (source). I noticed in my own testing that using numpy.loadtxt() was about twice as slow as the aforementioned manual method, which was also noted here.
I found that using pandas.from_csv().to_numpy(), I was able to get a speedup of ~10x that of looping through file.readlines(). See this answer here. Hopefully this helps anyone in the future with the same application.
uj5u.com熱心網友回復:
我正在嘗試使用 Numpy 對操作進行矢量化,以決議包含數字行的文本檔案并將資料轉換為 numpy 陣列。
矢量化與讀取資料無關。例如tmp.split(),仍然在一個普通的 Python 字串物件上呼叫一個普通的 Python 函式,結果創建了大量的 Python 字串物件,并在主要的 Python 位元組碼解釋器回圈中執行它。周圍的任何 Numpy 代碼都不會改變這一點。
也就是說,無論如何,這里沒有有意義的性能提升。與從硬碟驅動器中獲取內容相比,任何讀取和解釋(即決議)檔案的合理方法都將快如閃電,甚至比從 SSD 讀取要快得多。
我的方法是使用 file.readlines() 讀取行,然后將該行字串串列轉換為 numpy 陣列,如下所示 - file.readlines() 部分省略以進行測驗。
不要那樣做。整個程序比必要的復雜得多。繼續閱讀。
tmp = lines_array.tobytes().decode('ascii')
這只是為您提供檔案的原始內容,您可以直接使用.read()而不是.readlines().
從閱讀中我收集到“|S10”意味著陣列中的每個元素都是一個 10 個字符的字串,位元組順序無關緊要
不完全的; 這些元素是每個 10 位元組的陣列(在 C 意義上)。它們不是“字串”;它們是可能被解釋為文本的原始資料。
使用默認編碼將字串編碼為位元組時'1 0 0 0 0\n',使用 10 個位元組。中的所有其他字串也是如此。因此,“10 位元組陣列”是合適的 dtype。short_list
使用長串列呼叫會在每個字串的末尾插入幾個空字符 \x00,這使得決議變得更加困難。
它不插入“空字符”;它插入空位元組(數值為 0)。這樣做是因為它需要 15 個位元組來存盤 的編碼表示'14 0 0.5 0.5 0\n',并且每個元素必須具有相同的大小。
請記住,0您的文本中的符號被轉換為單個位元組,其數值不為零。它的數值為 48。
再說一遍:所有這些編碼和重新編碼步驟都沒有用 - 您可以使用檔案中的原始資料,通過.read()-.readlines()幫助您確定檔案中的行數。
但是您既不想也不需要這樣做。
你想要的邏輯直接內置在 Numpy 中。您應該通過使用搜索引擎自己發現了這一點。
你可以直接讓 Numpy 為你加載檔案,你應該這樣做:numpy.loadtxt('myfile.txt').
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/424190.html
上一篇:使用每行的值過濾np陣列
