簡體   English   中英

使用 numpy 對字符串列表進行多維切片

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM