将字符串操作应用于numpy数组?

时间:2011-11-11 05:08:27

标签: python numpy

是否有更好的方法将字符串操作应用于ndarray而不是迭代它们?我想使用“矢量化”操作,但我只能考虑使用map(示例显示)或列表推导。

Arr = numpy.rec.fromrecords(zip(range(5),'as far as i know'.split()),
                            names='name, strings')

print ''.join(map(lambda x: x[0].upper()+'.',Arr['strings']))
=> A.F.A.I.K.

例如,在R语言中,字符串操作也是矢量化的:

> (string <- unlist(strsplit("as far as i know"," ")))
[1] "as"   "far"  "as"   "i"    "know"
> paste(sprintf("%s.",toupper(substr(string,1,1))),collapse="")
[1] "A.F.A.I.K."

2 个答案:

答案 0 :(得分:16)

是的,最近的NumPy在numpy.char模块中进行了矢量化字符串操作。例如,当你想在字符串数组中找到以B开头的所有字符串时,那就是

>>> y = np.asarray("B-PER O O B-LOC I-LOC O B-ORG".split())
>>> y
array(['B-PER', 'O', 'O', 'B-LOC', 'I-LOC', 'O', 'B-ORG'], 
      dtype='|S5')
>>> np.char.startswith(y, 'B')
array([ True, False, False,  True, False, False,  True], dtype=bool)

答案 1 :(得分:14)

更新:请参阅Larsman's answer此问题:Numpy最近为基本字符串操作添加了numpy.char模块。

简答: Numpy没有提供矢量化字符串操作。惯用的方法是做一些事情(其中Arr是你的numpy数组):

print '.'.join(item.upper() for item in Arr['strings'])

很长的答案,这就是为什么numpy没有提供矢量化的字符串操作:(以及两者之间的漫游)

在数据结构方面,一种尺寸并不适合所有。

对于来自非特定领域的编程语言的人来说,您的问题可能看起来很奇怪,但对于来自特定领域语言的人来说,它很有意义。

Python为您提供了各种各样的数据结构选择。某些数据结构在某些任务中比其他任务更好。

首先,numpy数组不是默认值&#34; hold-all&#34; python中的容器。 Python的内置容器非常擅长于他们的设计目标。通常,列表或词典是你想要的。

Numpy的ndarray是针对同质数据的。

简而言之,numpy没有矢量化字符串操作。

ndarray是一个专门的容器,专注于在尽可能少的内存中存储N维同质项目组。重点在于最大限度地减少内存使用量(我有偏见,因为这主要是我所需要的,但它是一种有用的思考方式。)。矢量化数学运算只是将事物存储在连续的内存块中的一个很好的副作用。

字符串通常有不同的长度。

E.g。 ['Dog', 'Cat', 'Horse']。 Numpy采用类似数据库的方法,要求您为字符串定义长度,但字符串不是固定长度的简单事实有很多含义。

最有用的字符串操作返回可变长度字符串。 (例如,您的示例中为'.'.join(...)

如果你愿意的话,你可以模仿其他行动(例如鞋面等)。 (例如,鞋帮大约为(x.view(np.uint8) - 32).view('S1')。我不建议你这样做,但你可以......)

作为一个基本示例:'A' + 'B'会产生'AB''AB''A''B'的长度不同。 Numpy处理其他事情(例如np.uint8(4) + np.float(3.4)),但字符串的长度比数字更灵活。 (&#34; Upcasting&#34;&#34; downcasting&#34;数字规则非常简单。)

numpy没有做到的另一个原因是焦点在于数字操作。 'A'**2在python中没有特定的定义(你当然可以创建一个字符串类,但它应该是什么?)。字符串数组是numpy中的二等公民。它们存在,但大多数操作都没有为它们定义。

Python已经非常善于处理字符串处理

numpy没有尝试提供字符串操作的另一个(实际上,主要的)原因是python已经真正擅长它。

列表是非常灵活的容器。 Python有很多非常好的,非常快速的字符串操作。列表推导和生成器表达式相当快,并且他们不会因为他们不关心而试图猜测返回项目的类型或大小而遭受任何开销。 (他们只是存储一个指向它的指针。)

此外,在python中迭代numpy数组比在python中迭代列表或元组要慢,但对于字符串操作,你最好只使用普通的列表/生成器表达式。 (例如,在您的示例中为print '.'.join(item.upper() for item in Arr['strings']))更好的是,首先不要使用numpy数组来存储字符串。如果你有一个带有字符串的结构化数组的单列,那就有意义了。 Python为您提供了非常丰富而灵活的数据结构。 Numpy数组不是全部和最终的,它们是一个专门的案例,而不是一般情况。

另外,请记住,您想要使用numpy数组做的大部分内容

学习Python,而不仅仅是Numpy

我并不想在这里变得厚颜无耻,但使用numpy数组与Matlab或R或IDL等很多东西非常相似。

这是一个熟悉的范例,任何人的第一直觉就是尝试将相同的范例应用于其他语言。

Python不仅仅是numpy。它是一种多范式语言,因此很容易坚持你已经习惯的范式。尝试学习&#34;思考python&#34;以及只是&#34;在numpy&#34;中思考。 Numpy为python提供了一个特定的范例,但是那里有更多的范例,有些范例比其他范式更适合某些任务。

部分原因是熟悉不同数据容器的优缺点(列表与dicts vs元组等),以及不同的编程范例(例如面向对象与功能与程序等)。

总而言之,python有几种不同类型的专用数据结构。这使得它与特定于域的语言(如R或Matlab)略有不同,后者具有几种类型的数据结构,但专注于使用一种特定结构执行所有操作。 (我对R的经验是有限的,所以我可能在那里错了,但无论如何,这是我对它的印象。无论如何,这对Matlab来说确实如此。)

无论如何,我并没有试图在这里咆哮,但是我花了很长时间才停止在Matlab中编写Fortran,我花了更长时间才停止在python中编写Matlab。这个漫无边际的答案非常类似于具体的例子,但希望它至少有一点意义,并且有所帮助。