[英]Multi-dimensional slicing a list of strings with numpy
說我有以下幾點:
my_list = np.array(["abc", "def", "ghi"])
我想得到:
np.array(["ef", "hi"])
我試過:
my_list[1:,1:]
但后來我得到:
IndexError: too many indices for array
Numpy 是否支持切片字符串?
不,你不能那樣做。 對於numpy np.array(["abc", "def", "ghi"])
是一維字符串數組,因此不能使用2D切片。
您既可以將數組定義為2D數組或字符,也可以僅使用列表推導進行切片,
In [4]: np.asarray([el[1:] for el in my_list[1:]])
Out[4]:
array(['ef', 'hi'], dtype='|S2')
按照喬金頓在這里 ,蟒蛇是字符串操作和發電機很好/列表內涵是快速,靈活的字符串操作。 除非以后需要在管道中使用numpy
否則我強烈建議不numpy
。
[s[1:] for s in my_list[1:]]
快 :
In [1]: from string import ascii_lowercase
In [2]: from random import randint, choice
In [3]: my_list_rand = [''.join([choice(ascii_lowercase)
for _ in range(randint(2, 64))])
for i in range(1000)]
In [4]: my_list_64 = [''.join([choice(ascii_lowercase) for _ in range(64)])
for i in range(1000)]
In [5]: %timeit [s[1:] for s in my_list_rand[1:]]
10000 loops, best of 3: 47.6 µs per loop
In [6]: %timeit [s[1:] for s in my_list_64[1:]]
10000 loops, best of 3: 45.3 µs per loop
使用numpy
只會增加開銷。
您的字符串數組將數據存儲為連續的字符塊,使用'S3'dtype將其划分為長度為3的字符串。
In [116]: my_list
Out[116]:
array(['abc', 'def', 'ghi'],
dtype='|S3')
S1,S2
dtype將每個元素視為2個字符串,每個具有1和2個字符:
In [115]: my_list.view('S1,S2')
Out[115]:
array([('a', 'bc'), ('d', 'ef'), ('g', 'hi')],
dtype=[('f0', 'S1'), ('f1', 'S2')])
選擇第二個字段以獲取具有所需字符的數組:
In [114]: my_list.view('S1,S2')[1:]['f1']
Out[114]:
array(['ef', 'hi'],
dtype='|S2')
我對view
第一次嘗試是將數組拆分為單字節字符串,然后使用生成的2d數組進行播放:
In [48]: my_2dstrings = my_list.view(dtype='|S1').reshape(3,-1)
In [49]: my_2dstrings
Out[49]:
array([['a', 'b', 'c'],
['d', 'e', 'f'],
['g', 'h', 'i']],
dtype='|S1')
然后可以在兩個維度上切片此數組。 我使用了flatten
來刪除尺寸,並強制復制(以獲取新的連續緩沖區)。
In [50]: my_2dstrings[1:,1:].flatten().view(dtype='|S2')
Out[50]:
array(['ef', 'hi'],
dtype='|S2')
如果字符串已經在數組中(而不是列表),則此方法比列表理解方法快得多。
wflynny
測試的1000 x 64列表的一些計時
In [98]: timeit [s[1:] for s in my_list_64[1:]]
10000 loops, best of 3: 173 us per loop # mine's slower computer
In [99]: timeit np.array(my_list_64).view('S1').reshape(64,-1)[1:,1:].flatten().view('S63')
1000 loops, best of 3: 213 us per loop
In [100]: %%timeit arr =np.array(my_list_64)
.....: arr.view('S1').reshape(64,-1)[1:,1:].flatten().view('S63') .....:
10000 loops, best of 3: 23.2 us per loop
從列表創建數組很慢,但是一旦創建, view
方法就會快得多。
請參閱我的編輯歷史記錄,以獲取有關np.char
早期筆記。
從 numpy 1.23.0 開始,我添加了一種機制來更改非連續數組的視圖的 dtype。 這意味着您可以將數組視為單個字符,按照您喜歡的方式對其進行切片,然后將其重新組合在一起。 在這之前需要一份副本,正如@hpaulj 的回答清楚地顯示的那樣。
>>> my_list = np.array(["abc", "def", "ghi"])
>>> my_list[:, None].view('U1')[1:, 1:].view('U2').squeeze()
array(['ef', 'hi'])
我正在研究另一層抽象,專門用於名為np.slice_
字符串數組(目前正在PR #20694 中進行,但代碼是可用的)。 如果這應該被接受,你將能夠做到
>>> np.char.slice_(my_list[1:], 1)
array(['ef', 'hi'])
您的切片語法錯誤。 您只需要執行my_list[1:]
即可獲得所需的內容。 如果要將元素兩次復制到列表中,則可以執行以下操作something = mylist[1:].extend(mylist[1:])
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.