【问题标题】:Extract the first letter from each string in a numpy array从numpy数组中的每个字符串中提取第一个字母
【发布时间】:2018-06-27 11:23:31
【问题描述】:

我有一个巨大的 numpy 数组,其中元素是字符串。我喜欢用字符串的第一个字母替换字符串。例如,如果

C[0] = 'A90CD'

我想换成

C[0] = 'A'

简而言之,我正在考虑在循环中应用正则表达式,其中我有一个像

这样的正则表达式字典

'^A.+$' => 'A'

'^B.+$' => 'B' 等等

如何在 numpy 数组上应用这个正则表达式?或者有没有更好的方法来达到同样的效果?

【问题讨论】:

  • 所有字符串都以字母开头还是要提取像02AC9这样的字符串的第一个字母?
  • 是的,所有字符串都以字母开头。但是,实际上,我对字符串的第一个字母感兴趣。
  • 好吧,那么您从 Coldspeed 得到了答案。
  • 数组中所有字符串的长度是否相同?
  • 是的,所有字符串的长度都相同

标签: python arrays string numpy


【解决方案1】:

这里不需要正则表达式。只需使用 astype 将您的数组转换为 1 字节字符串 -

v = np.array(['abc', 'def', 'ghi'])

>>> v.astype('<U1')
array(['a', 'd', 'g'],
      dtype='<U1')

或者,您可以更改其view 和步幅。这是针对大小相等的字符串的稍微优化的版本。 -

>>> v.view('<U1')[::len(v[0])]
array(['a', 'd', 'g'],
      dtype='<U1')

这是.view 方法的更通用版本,但这适用于长度不同的字符串数组。感谢 Paul Panzer suggestion -

>>> v.view('<U1').reshape(v.shape + (-1,))[:, 0]
array(['a', 'd', 'g'],
      dtype='<U1')

性能

y = np.array([x * 20 for x in v]).repeat(100000)

y.shape
(300000,)

len(y[0])   # they're all the same length - `abcabcabc...`
60

现在,时间安排 -

# `astype` conversion

%timeit y.astype('<U1')
100 loops, best of 3: 5.03 ms per loop

# `view` for equal sized string arrays 

%timeit y.view('<U1')[::len(y[0])]
100000 loops, best of 3: 2.43 µs per loop

# Paul Panzer's version for differing length strings

%timeit y.view('<U1').reshape(y.shape + (-1,))[:, 0]
100000 loops, best of 3: 3.1 µs per loop

view 方法快很多

但是,请谨慎使用,因为内存是共享的。


如果您对找到第一个字母的更通用的解决方案感兴趣(无论它可能在哪里),我会说最快/最简单的方法是使用@987654334 @ 模块,编译模式并在列表理解中搜索。

>>> p = re.compile('[a-zA-Z]')
>>> [p.search(x).group() for x in v]
['a', 'd', 'g']

而且,它在上述相同设置下的性能 -

%timeit [p.search(x).group() for x in y]
1 loop, best of 3: 320 ms per loop

【讨论】:

  • view-slice 方法比 astype 方法有优势吗?
  • @Piinthesky 实际上我不确定(刚回来让它更干净)。我应该做一些时间来看看....会及时通知你。
  • .view-slice 不占用任何额外的内存,它只是指针。 .astype 复制一份。除了好处之外,.view 也应该允许您更改这些首字母。
  • 字符串不必是相同的长度才能使视图投射起作用。只需strarr.view('&lt;U1').reshape(strarr.shape + (-1,))[..., 0],可能会警告数据是共享的。
  • @cᴏʟᴅsᴘᴇᴇᴅ 我认为view 可以做到这一点并不令人惊讶,因为 AFAIK numpy zeropad 将所有字符串都设置为相同的长度。试试np.array('Hi, I am an example.'.split()).view('&lt;U1')
猜你喜欢
  • 1970-01-01
  • 2021-10-14
  • 2018-07-11
  • 1970-01-01
  • 2014-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-12
相关资源
最近更新 更多