python - 将 NumPy np.uint8 数组列表转换为 np.unicode_ 数组
问题描述
我有一个 NumPy 可变大小数组的列表dtype=np.uint8
(这些代表 UTF-8 编码的字符串)。如何有效快速地将此列表转换为单个dtype=np.unicode_
数组?
l = [np.frombuffer(b'asd', dtype = np.uint8), np.frombuffer(b'asdasdas', dtype = np.uint8)]
# The following will work, but will first create a temporary string which is inefficient.
# I'm looking for a method that would directly allocate a target np.unicode_-typed array
# and encode the data into it.
a = np.array([s.tostring().decode('utf-8') for s in l])
这些数组不仅是 ASCII 编码的,它们还包含其他字符:
s = b'8 \xd0\x93\xd0\xbe\xd1\x80\xd0\xbe\xd0\xb4 \xd0\x91\xd0\xb0\xd0\xb9\xd0\xba\xd0\xbe\xd0\xbd\xd1\x83\xd1\x80 (\xd0\xa0\xd0\xb5\xd1\x81\xd0\xbf\xd1\x83\xd0\xb1\xd0\xbb ...: \xd0\xb8\xd0\xba\xd0\xb0 \xd0\x9a\xd0\xb0\xd0\xb7\xd0\xb0\xd1\x85\xd1\x81\xd1\x82\xd0\xb0\xd0\xbd)'
s.decode('utf-8') # works
解决方案
更新
事实证明,Python utf-8 编解码器可用于直接解码 ndarray,而无需先将其内容复制到字节字符串.tostring()
:使用编解码器模块,可以检索将 utf-8 字节序列转换为 unicode 的可调用对象无需经过的字符串str.decode
lst = [np.frombuffer(b'asd', dtype = np.uint8), np.frombuffer(b'asdasdas', dtype = np.uint8)]
import codecs
decoder = codes.getdecoder("utf-8")
data = np.array([decoder(item)[0] for item in lst], dtype="unicode")
这避免了转换的一个步骤 - 可以避免另一个步骤,因为这仍然会在调用最后一个.array
构造函数之前创建内存中所有字符串的列表 - numpy 有一个.fromiter
数组构造函数 - 但它不能创建一个数组任意 unicode 对象 - 它需要一个固定的字符宽度。这最终会消耗比目前更多的内存:
data = np.fromiter((decoder(item) for item in lst), count=len(lst), dtype="U120") # For max-length of 120 characters.
原始答案(主要是罗马漫谈)
现代 Python 内部处理 Unicode 文本非常有效,内部 unicode 点表示取决于字符串中最宽的字符。
另一方面,Numpy 只为每个 unicode 字符存储一个 32 位的值——它没有业务“理解”utf-8。Python 语言在这方面做得很好——而且速度很快。尽管 Python 在将 utf-8 字节解码为文本时不会使用任何多线程、多核或硬件加速策略,但解码是在本机代码中进行的,并且与您在单个 CPU 内核中获得的速度一样快。
在我的系统中,使用纯 Python 将 4MB 大小的文本解码为 unicode 只需不到 30 毫秒。
换句话说:你开始担心错误的问题——除非你正在编码的任何东西都需要以持续的方式每秒转换大约 100 个圣经大小的文本语料库。
只需让 Python 进行 utf-8 解码,并将结果处理回 numpy(它将以 32 位格式再次对其进行编码) - 对于绝大多数现实世界的任务来说,这方面的花费可以忽略不计,这是例如,Pandas 库对数据执行几乎所有操作的方式:在每次操作后创建数据的新副本。
推荐阅读
- reactjs - 如何把它变成一个函数
- yocto - 添加/编辑 .bbappend 文件时应如何处理增加包修订?
- visual-studio - 在 Visual Studio 中,如何有效地使用 NuGet 包源代码
- vim - Vim 映射 Cntrl-i 在正常和插入之间切换
- python - 如何合并重复的列以获得多行而不是多列或逗号分隔的数据到单个单元格中?
- c++ - 函数模板特化生成链接错误
- python - 函数如何在这个 for 循环之外执行?
- python - 如何在绘制分布曲线时在 x_axis 中绘制月/年?
- html - 如何防止网格列随着文本的增加而改变大小(html/css)?
- bash - 逐行比较 4 个文件,看它们是否匹配