如何在 numpy 中创建字符数组?

Posted

技术标签:

【中文标题】如何在 numpy 中创建字符数组?【英文标题】:How do I create character arrays in numpy? 【发布时间】:2012-03-17 14:54:33 【问题描述】:

假设我有以下数组:

import numpy as np
a = ['hello','snake','plate']

我希望它变成一个 numpy 数组 b 以便:

b[0,0] = 'h'
b[0,1] = 'e'
b[0,2] = 'l'
b[1,0] = 's'
...

我希望标准的 numpy 技巧起作用,例如广播、比较等。

它是如何完成的?这在 numpy 文档中的什么位置?

谢谢!

乌里

【问题讨论】:

【参考方案1】:

将字符串长度指定为形状参数,unicode 1 char

> string_array = ['..##.#..#.', '##..#.....', '#...##..#.', '####.#...#', '##.##.###.', '##...#.###', '.#.#.#..##', '..#....#..', '###...#.#.', '..###..###']
> numpy.array(string_array,dtype=('U1',10))
array([['.', '.', '#', '#', '.', '#', '.', '.', '#', '.'],
       ['#', '#', '.', '.', '#', '.', '.', '.', '.', '.'],
       ['#', '.', '.', '.', '#', '#', '.', '.', '#', '.'],
       ['#', '#', '#', '#', '.', '#', '.', '.', '.', '#'],
       ['#', '#', '.', '#', '#', '.', '#', '#', '#', '.'],
       ['#', '#', '.', '.', '.', '#', '.', '#', '#', '#'],
       ['.', '#', '.', '#', '.', '#', '.', '.', '#', '#'],
       ['.', '.', '#', '.', '.', '.', '.', '#', '.', '.'],
       ['#', '#', '#', '.', '.', '.', '#', '.', '#', '.'],
       ['.', '.', '#', '#', '#', '.', '.', '#', '#', '#']], dtype='<U1')

这显然不应该奏效 - https://github.com/numpy/numpy/issues/18407 并在 numpy 1.20.1 中停止工作,但一个简单的替换是

numpy.array(list(map(list, string_array)))

在 numpy 接收之前将字符串列表转换为 char 列表的列表,避免了显式设置 dtype 的需要。

【讨论】:

我认识这个输入!它是来自Advent of Code 2020 Day 20 的样本数据中的第一个图块。【参考方案2】:

实际上,您可以在 numpy 中不使用任何副本或列表推导来执行此操作(除了关于非等长字符串的警告......)。只需将其视为 1 个字符的字符串数组并对其进行整形:

import numpy as np

x = np.array(['hello','snake','plate'], dtype=str)
y = x.view('S1').reshape((x.size, -1))

print repr(y)

这会产生:

array([['h', 'e', 'l', 'l', 'o'],
       ['s', 'n', 'a', 'k', 'e'],
       ['p', 'l', 'a', 't', 'e']], 
      dtype='|S1')

不过,一般来说,在大多数情况下,我会避免使用 numpy 数组来存储字符串。在某些情况下它很有用,但您通常最好坚持使用允许可变长度字符串的数据结构,好吧,保存字符串。

【讨论】:

对于 python3,如果字符串是 ascii 字符串,则需要编写 dtype=bytes 如果你想让 Unicode 字符串工作,改变 dtype=np.unicode_ 和 view('U1')【参考方案3】:

您可以直接创建一个numpy字符数组,例如:

b = np.array([ ['h','e','l','l','o'],['s','n','a','k','e'],['p','l','a','t','e'] ])

通常的数组技巧适用于此。

如果您有a 并希望从中生成 b,请注意:

list('hello') == ['h','e','l','l','o']

所以你可以这样做:

b = np.array([ list(word) for word in a ])

但是,如果a 有不等长的单词(例如['snakes','on','a','plane']),你想如何处理较短的单词?您可以用空格填充最长的单词:

wid = max(len(w) for w in a)
b = np.array([ list(w.center(wid)) for w in a])

string.center(width) 用空格填充,使字符串居中。您也可以使用rjustljust(参见string docs)。

【讨论】:

谢谢,这可能对我有用。但我想知道是否有一种方法我不必使用列表理解?我将不得不多次执行此操作(要启动更大的阵列)。是否有一个 numpy 命令可以处理已编译代码中的循环? 我不知道有任何 numpy 命令专门将字符串拆分为单个字母,同时强制转换为矩阵。我认为您可能会被列表推导所困(但我们会看到,也许有人知道这样做的魔术函数)。

以上是关于如何在 numpy 中创建字符数组?的主要内容,如果未能解决你的问题,请参考以下文章

如何在numpy中创建一个连续数字数组?

如何根据字符串数量的输入在 C++ 中创建数组?

如何在 NumPy 中创建一个空数组/矩阵?

如何在 C++ 中创建类似于 Python 的 numpy 数组的数组?

如何在 Typescript 中创建一个空字符串数组?

如何从字符串数组在 json 字符串中创建层次结构?