用numpy多维切片字符串列表

时间:2015-07-13 15:10:15

标签: python arrays numpy multidimensional-array slice

说我有以下内容:

my_list = np.array(["abc", "def", "ghi"])

我想得到:

np.array(["ef", "hi"])

我试过了:

my_list[1:,1:]

但后来我得到了:

IndexError: too many indices for array

Numpy是否支持切片?

4 个答案:

答案 0 :(得分:2)

不,你不能这样做。对于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')

答案 1 :(得分:0)

根据Joe Kington here,python非常擅长字符串操作,并且生成器/列表理解对于字符串操作来说是快速且灵活的。除非您需要在管道中稍后使用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只会增加开销。

答案 2 :(得分:0)

您的字符串数组将数据存储为连续的字符块,使用“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')

如果字符串已经在数组中(而不是列表),那么这种方法比列表理解方法快得多。

一些1000 x 64列表wflynny测试

的时间
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的说明的编辑历史记录。

答案 3 :(得分:-2)

您的切片语法不正确。您只需my_list[1:]即可获得所需内容。如果要将元素两次复制到列表中,可以执行something = mylist[1:].extend(mylist[1:])