首页 > 解决方案 > 将 numpy 字符串数组转换为 numpy 矩阵

问题描述

所以我有一个 numpy 字符串数组,其中包含用空格分隔的数值,例如:

np.array(['1 2', '3 4'])
array(['1 2', '3 4'], dtype='<U3')

我想将它转换为一个数字矩阵,如:

np.array([[1,2],[3,4]])
array([[1, 2],[3, 4]])

我正在寻找一种可以利用 numpy vecotrized 操作的操作,因为速度在这里很重要。在此示例中,行的长度为 2,但我需要一种具有任意行长度的通用方法。

谢谢!

标签: pythonarraysstringnumpycharacter

解决方案


这是一种方法,假设非负整数成对出现,由一个空格分隔:

def to_num(x):                                          
    y = (x[:,None].view(np.int32)-48)*10**np.arange(x.itemsize//4-1,-1,-1)                    
    splt = y.argmin(1)                                                                        
    z = np.take_along_axis(y.cumsum(1),np.column_stack([splt-1,np.full(*y.shape-np.arange(2))]),1)
    z[:,1]+=10**(y.shape[1]-splt-1)*16-z[:,0]                                                    
    z[:,0]//=10**(y.shape[1]-splt)                                                               
    end = (y[:,::-1]>=0).argmax(1)
    z[:,1]+=np.concatenate([[0],48*np.cumsum(10**np.arange(end.max()))])[end]
    z[:,1]//=10**end
    return z

例如,10^6 对在我的机器上大约需要 3 秒:

from timeit import timeit

x = np.random.randint(0,1000000,(1000000,2))
x = np.array([" ".join(map(str, y)) for y in x.tolist()])

(to_num(x) == [[int(z) for z in y.split()] for y in x.tolist()]).all()
# True
timeit(lambda:to_num(x), number=10)
# 2.9360161621589214

推荐阅读