A1 作为字节串数组加载。 Python3 默认使用 unicode 字符串,因此通常在它们前面加上 'b'。这对于print 来说是正常的。我有点惊讶它在文件写入期间也是如此。
无论如何,这似乎可以解决问题:
A2=np.array([x.decode() for x in A1])
np.savetxt("Test.txt", A2, fmt='%s', delimiter=',')
A2 的 dtype 类似于 dtype='<U100'。
我的测试数组是:
array([b'one.com', b'two.url', b'three.four'], dtype='|S10')
从一个简单的文本文件加载:
one.com
two.url
three.four
.decode 是一个字符串方法。 [x.decode() for x in A1] 适用于简单的一维字节串数组。如果A1 是2d,则必须对所有元素进行迭代,而不仅仅是行。如果A1 是结构化数组,则必须将其应用于元素内的字符串。
另一种可能性是在加载期间使用转换器,因此您会得到一个 (unicode) 字符串数组
In [508]: A1=np.loadtxt('urls.txt', dtype='U',
converters={0:lambda x:x.decode()})
In [509]: A1
Out[509]:
array(['one.com', 'two.url', 'three.four'], dtype='<U10')
In [510]: np.savetxt('test0.txt',A1,fmt='%s')
In [511]: cat test0.txt
one.com
two.url
three.four
包含loadtxt 的库有几个转换器函数asbytes、asbytes_nested 和asstr。所以converters 也可以是:converters={0:np.lib.npyio.asstr}。
genfromtxt 在没有 converters 的情况下处理这个问题:
A1=np.genfromtxt('urls.txt', dtype='U')
# array(['one.com', 'two.url', 'three.four'], dtype='<U10')
要理解为什么savetxt 保存我们想要的unicode 字符串,但附加b 用于字节字符串,我们必须查看它的代码。
np.savetxt(在 py3 上运行)本质上是:
fh = open(fname, 'wb')
X = np.atleast_2d(X).T
# make a 'fmt' that matches the columns of X (with delimiters)
for row in X:
fh.write(asbytes(format % tuple(row) + newline))
查看两个示例字符串(str 和 bytesstr):
In [617]: asbytes('%s'%tuple(['one.two']))
Out[617]: b'one.two'
In [618]: asbytes('%s'%tuple([b'one.two']))
Out[618]: b"b'one.two'"
写入“wb”文件会删除b'' 的外层,留下字节串的内层。它还解释了为什么将字符串('plain' py3 unicode)作为 'latin1' 字符串写入文件。
你可以直接写一个字节串数组,不用savetxt。例如:
A0 = array([b'one.com', b'two.url', b'three.four'], dtype='|S10')
with open('test0.txt','wb') as f:
for x in A0:
f.write(x+b'\n')
cat test0.txt
one.com
two.url
three.four
Unicode 字符串也可以直接写入,生成相同的文件:
A1 = array(['one.com', 'two.url', 'three.four'], dtype='<U10')
with open('test1.txt','w') as f:
for x in A1:
f.write(x+'\n')
此类文件的默认编码为encoding='UTF-8',与'one.com'.encode() 使用的相同。效果和savetxt一样:
with open('test1.txt','wb') as f:
for x in A1:
f.write(x.encode()+b'\n')
np.char 具有 .encode 和 .decode 方法,它们似乎对数组的元素进行迭代操作。
因此
np.char.decode(A1) # convert |S10 to <U10, like [x.decode() for x in A1]
np.char.encode(A1) # convert <U10 to |S10
这适用于多维数组
np.savetxt('testm.txt',np.char.decode(A_bytes[:,None][:,[0,0]]),
fmt='%s',delimiter=', ')
对于结构化数组,np.char.decode 必须单独应用于每个字符字段。