Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python NumPy数组中每个字符串的长度_Python_Python 3.x_Numpy - Fatal编程技术网

Python NumPy数组中每个字符串的长度

Python NumPy数组中每个字符串的长度,python,python-3.x,numpy,Python,Python 3.x,Numpy,NumPy中是否有任何内置操作返回数组中每个字符串的长度 我不认为有人会这么做,对吗 我可以用for循环来完成,但也许有更有效的方法 import numpy as np arr = np.array(['Hello', 'foo', 'and', 'whatsoever'], dtype='S256') sizes = [] for i in arr: sizes.append(len(i)) print(sizes) [5, 3, 3, 10] 对我来说,这是一条路: size

NumPy中是否有任何内置操作返回数组中每个字符串的长度

我不认为有人会这么做,对吗

我可以用
for
循环来完成,但也许有更有效的方法

import numpy as np
arr = np.array(['Hello', 'foo', 'and', 'whatsoever'], dtype='S256')

sizes = []
for i in arr:
    sizes.append(len(i))

print(sizes)
[5, 3, 3, 10]

对我来说,这是一条路:

sizes = [len(i) for i in arr]

您可以使用
numpy
vectorize
。速度快得多

mylen = np.vectorize(len)
print mylen(arr)

更新06/20:适合u+0000字符和非连续输入-感谢@M1L0U

下面是两种方法的比较

意见:

  • 对于输入大小>1000行的情况,viewcasting+
    argmax
    始终是最快的
  • Python解决方案首先从将数组转换为列表中获益
  • map
    beats列表理解
  • np.frompyfunc
    和在较小程度上
    np.vectorize
    比他们的声誉要好

代码:


使用
Numpy
中的
stru-len

sizes = np.char.str_len(arr)

str_len documentation:

在我的计时中,mylen明显比这个小示例数组的列表理解慢,而对于1000倍大的数组,它的理解速度几乎没有提高<代码>矢量化不保证速度。它确实使迭代多维数组的所有元素变得更容易。@hpaulj我指的是for循环。这比正常情况下要快,如果数据很大,它仍然比列表理解快。数据事项.)与pandas相比,这比df['s']快。str.len()在Numpy中,这个标准操作没有一个线性
np.vectorize(len)(arr)
很奇怪。之所以
np.vectorize
没有更快,是因为
np.vectorize
只是运行了一个Python for循环,它没有编译。事实上,这一缺陷正是Numba写作的原因。Travis Oliphant(NumPy的作者)说得很对:对于中等大小的数组,列表理解等价物是好的:
[len(i)For i in arr]
np.char
函数也不是很快,因为它们仍然必须对每个元素应用
string
方法。不要回答太多!使用
argmin
的技巧很好,但它有一个边缘大小写:它找到第一个
'\x00'
,它不一定是字符串的结尾。在大多数情况下,尤其是unicode字符串,唯一的“\x00”在末尾,但某些字符串(如字节)可能在任何位置包含一些。为了找到字符串的大小,我们需要计算从右边开始有多少个
'\x00'
。例如,这可以通过
(numpy.cumsum((v!=0)[:,:-1],axis=1)>0)来实现。sum(axis=1)
Hi@M1L0U我已经有一段时间没有写过这个答案了,但我认为它是正确的。请注意,我并没有强制转换为byte,而是转换为uint32,这与numpy
U.
dtype是一种4字节固定宽度编码这一事实相匹配。我认为四个对齐的零字节在任何地方都是不可能的,除了作为结束标记。还是真的?这在技术上是可能的,但很奇怪。除了“错误地”将原始字节转换为unicode字符串之外,我没有看到其他用例
A=numpy.array(['ABC\x00DEF','A\x00BC'])
是一个从
numpy
的角度来看非常有效的
U7
数组view@M1L0U天哪,你说得对。显然,u+0000是有效的unicode。我会更新这篇文章。因为我喜欢边缘案例,这里有另一个^^^(可能对谷歌搜索有用)。如果数组不是C连续的,则
视图(np.uint32)
将失败。这样的事情通常发生在使用
步骤进行切片之后=1
。例如做
A[:-1]
。要解决此问题,可以在
.view
之前添加
A=numpy.asarray(A,order='C')
。请注意,它仅在需要时复制数据。这是迄今为止对该问题的最佳答案。请投票!它需要在顶端!
import numpy as np

flist = []
def timeme(name):
    def wrap_gen(f):
        flist.append((name, f))
        return(f)
    return wrap_gen

@timeme("np.char.str_len")
def np_char():
    return np.char.str_len(A)

@timeme("list comprehension")
def lst_cmp():
    return [len(a) for a in A]

@timeme("list comprehension after .tolist()")
def lst_cmp_opt():
    return [len(a) for a in A.tolist()]

@timeme("map")
def map_():
    return list(map(len, A.tolist()))

@timeme("np.frompyfunc")
def np_fpf():
    return np.frompyfunc(len, 1, 1)(A)

@timeme("np.vectorize")
def np_vect():
    return np.vectorize(len)(A)
    
@timeme("safe argmax")
def np_safe():
    assert A.dtype.kind=="U"
    # work around numpy's refusal to viewcast non contiguous arrays
    v = np.lib.stride_tricks.as_strided(
        A[0,None].view("u4"),(A.size,A.itemsize>>2),(A.strides[0],4))
    v = v[:,::-1].astype(bool)
    l = v.argmax(1)
    empty = (~(v[:,0]|l.astype(bool))).nonzero()
    l = v.shape[1]-l
    l[empty] = 0
    return l
    
A = np.random.choice(
    "Blind\x00text do not use the quick brown fox jumps over the lazy dog "
    .split(" "),1000000)[::2]

for _, f in flist[:-1]:
    assert (f()==flist[-1][1]()).all()

from timeit import timeit

for j,tag in [(1,"contiguous"),(2,"non-contiguous")]:
    print('\n',tag)
    L = ['|+' + len(flist)*'|',
         [f"{'method ↓↓                  size →→':36s}", 36*'-']
         + [f"{name:36s}" for name, f in flist]]
    for N in (10, 100, 1000, 10000, 100000, 1000000):
        A = np.random.choice("Blind\x00text do not use the quick brown fox"
                             " jumps over the lazy dog ".split(" "),j*N)[::j]
        L.append([f"{N:>7d}", 7*'-']
                 + [f"{timeit(f, number=10)*100:7.3f}" for name, f in flist])
    for sep, *line in zip(*L):
        print(*line, sep=sep)
sizes = np.char.str_len(arr)