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

8

除了迭代,有没有更好的方法将字符串操作应用于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."

1
我不明白为什么你想要使用numpy来处理字符串。你希望获得什么优势?Python的字符串处理已经很好了,使用numpy会有什么更好的地方吗? - steveha
print ''.join(s[0].upper() + '.' for s in "as far as i know".split()) - steveha
1
@steveha:我认为OP想要并行运行这些操作,即“矢量化”。但是我不认为这会实现OP想要做的事情。 - Xavier Ho
1
@steveha:这个例子只是一个玩具示例,很明显我不需要使用数组,但我故意将字符串包含在记录数组中,以表明这是应用程序:字符串数组通常随其他变量一起在数组中传递(可以插入/删除记录)。 - hatmatrix
@crippledlambda - 如果你经常插入和/或删除值,numpy数组是一个不好的选择。它们旨在成为一种内存高效的容器,而不是一种灵活的容器。Python列表似乎更适合你的问题。 - Joe Kington
显示剩余5条评论
2个回答

17

是的,最近的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)

14

更新: 请参考Larsman的答案,他回答了这个问题: Numpy最近添加了一个numpy.char模块,用于基本字符串操作。

简短回答: Numpy没有提供向量化的字符串操作。惯用的方法是执行这样的操作(其中Arr是您的numpy数组):

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

为什么numpy不提供向量化的字符串操作:numpy数组是专门用于存储 N 维同构数据的一种容器,强调尽可能节省内存。字符串不像数字那样长度固定,大多数有用的字符串操作返回可变长度字符串,而numpy数组的操作通常不适用于字符串。Python本身已经非常擅长处理字符串,列表也是一个很好的灵活容器,可以使用列表解析和生成器表达式来进行字符串操作。因此,对于字符串操作,最好还是只使用正常的列表/生成器表达式,而不是将字符串存储在numpy数组中。

当涉及到数据结构时,没有一种“万能”的数据结构适用于所有情况。Python提供了多种不同的数据结构选择,每种数据结构都有其自己的优势和适用范围。numpy数组并不是Python中默认的“全能”容器,因为Python的内置容器在它们设计的领域内非常出色,通常情况下列表或字典更适合我们的需求。最后,学习Python时,应该注意到Python是一种多范式语言,有多种不同的数据容器和编程范式可供选择,不应过分依赖numpy数组。


1
这是我读过的关于NumPy数组在Python科学能力中作用最有见地的评论。我从未遇到过这种观点,但考虑到ndarray的“限制”,这是完全有道理的;这些数组可能最好在用户定义的类内使用,该类还使用元组和列表来处理与数组相关的“元数据”。 - hatmatrix
2
我最近几周开始尝试使用pandas数据框架,但似乎它是为提供与R数据框架和SQL表常见操作相关的类型而创建的。数据框架的优点在于已经定义了许多用于操作科学或统计数据的常见操作;因此,我认为出于这个原因我可能会进一步研究pandas。 - hatmatrix
1
顺便说一句,R确实拥有向量、列表/字典、元组、哈希表、矩阵、数组、数据框架、用户自定义对象等,但在许多操作中它集中于数据框架,尽管有大量的矩阵操作,而且较少程度上定义了数组操作。Matlab随着时间的推移也增加了数据结构(列表/单元数组和数据结构),但我发现该语言对其定义的操作要更加简洁(因此需要手动将其“解包”为数组,然后再对其内容进行操作)。 - hatmatrix
1
简短的回答已经过时,这表明长篇回答是错误的。NumPy现在具有向量化字符串操作,当处理大量短字符串时非常有用。请参见我的答案以获取示例。 - Fred Foo
@larsmans - 确实,新的np.char模块非常有用,但这并不意味着长部分是不正确的。如果您有大量短字符串,则numpy数组可能是有意义的。然而,从matlab转到python的人经常希望在列表更为合适的情况下使用numpy数组。(例如,考虑对一个字符串numpy数组进行加法运算。)这就是我试图解释“长答案”部分的内容。尽管如此,请原谅我的小小的个人观点。无论如何,您提出了很好的观点。 - Joe Kington

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接