将numpy数组转换为CSV字符串,再将CSV字符串转换回numpy数组

14

我需要将一个包含浮点数的numpy数组转换为字符串(以便存储在SQL数据库中),然后再将同一字符串转换回numpy浮点数数组。

以下是我根据这篇文章的方法将其转换为字符串:

VIstring = ''.join(['%.5f,' % num for num in VI])
VIstring= VIstring[:-1] #Get rid of the last comma

首先,这种方法确实有效,但是有更好的方法来消除最后的逗号吗?或者我可以让 join 方法为我插入逗号吗?

其次,更重要的是,有没有聪明的方法从字符串恢复到浮点数数组?

下面是数组和字符串的示例:

VI
array([ 17.95024446,  17.51670904,  17.08894626,  16.66695611,
        16.25073861,  15.84029374,  15.4356215 ,  15.0367219 ,
        14.64359494,  14.25624062,  13.87465893,  13.49884988,
        13.12881346,  12.76454968,  12.40605854,  12.00293814,
        11.96379322,  11.96272486,  11.96142533,  11.96010489,
        11.95881595,  12.26924591,  12.67548634,  13.08158864,
        13.4877041 ,  13.87701221,  14.40238245,  14.94943786,
        15.49364166,  16.03681428,  16.5498035 ,  16.78362298,
        16.90331119,  17.02299387,  17.12193689,  17.09448654,
        17.00066063,  16.9300633 ,  16.97229868,  17.2169709 ,  17.75368411])

VIstring
'17.95024,17.51671,17.08895,16.66696,16.25074,15.84029,15.43562,15.03672,14.64359,14.25624,13.87466,13.49885,13.12881,12.76455,12.40606,12.00294,11.96379,11.96272,11.96143,11.96010,11.95882,12.26925,12.67549,13.08159,13.48770,13.87701,14.40238,14.94944,15.49364,16.03681,16.54980,16.78362,16.90331,17.02299,17.12194,17.09449,17.00066,16.93006,16.97230,17.21697,17.75368'

没错,%.5f 的精度损失完全没关系,因为这些值只是由原始点进行插值得到的,而原始点只有4位小数精度,所以我不需要超过这个精度。因此,在恢复 numpy 数组时,我很高兴只获得 5 位小数精度(显然我认为如此)。


1
你可以查看numpy的savetxt和loadtxt函数。 - Matt
@MattAnderson 有没有办法将这些内容直接放入字符串中,并从内存中直接加载,而不是使用文件? - Dan
3个回答

25

首先,您应该使用以下方式使用join来避免最后一个逗号的问题:

VIstring = ','.join(['%.5f' % num for num in VI])

然后要读回它,使用numpy.fromstring

np.fromstring(VIstring, sep=',')

非常好的函数建议 @Boud。 - Pramit
不客气 @Pramit:pandas 强大到让用户忘记了 numpy 的底层特性。 - Zeugma

9
>>> import numpy  as np
>>> from cStringIO import StringIO
>>> VI = np.array([ 17.95024446,  17.51670904,  17.08894626,  16.66695611,
        16.25073861,  15.84029374,  15.4356215 ,  15.0367219 ,
        14.64359494,  14.25624062,  13.87465893,  13.49884988,
        13.12881346,  12.76454968,  12.40605854,  12.00293814,
        11.96379322,  11.96272486,  11.96142533,  11.96010489,
        11.95881595,  12.26924591,  12.67548634,  13.08158864,
        13.4877041 ,  13.87701221,  14.40238245,  14.94943786,
        15.49364166,  16.03681428,  16.5498035 ,  16.78362298,
        16.90331119,  17.02299387,  17.12193689,  17.09448654,
        17.00066063,  16.9300633 ,  16.97229868,  17.2169709 ,  17.75368411])
>>> s = StringIO()
>>> np.savetxt(s, VI, fmt='%.5f', newline=",")
>>> s.getvalue()
'17.95024,17.51671,17.08895,16.66696,16.25074,15.84029,15.43562,15.03672,14.64359,14.25624,13.87466,13.49885,13.12881,12.76455,12.40606,12.00294,11.96379,11.96272,11.96143,11.96010,11.95882,12.26925,12.67549,13.08159,13.48770,13.87701,14.40238,14.94944,15.49364,16.03681,16.54980,16.78362,16.90331,17.02299,17.12194,17.09449,17.00066,16.93006,16.97230,17.21697,17.75368,'
>>> np.fromstring(s.getvalue(), sep=',')
array([ 17.95024,  17.51671,  17.08895,  16.66696,  16.25074,  15.84029,
        15.43562,  15.03672,  14.64359,  14.25624,  13.87466,  13.49885,
        13.12881,  12.76455,  12.40606,  12.00294,  11.96379,  11.96272,
        11.96143,  11.9601 ,  11.95882,  12.26925,  12.67549,  13.08159,
        13.4877 ,  13.87701,  14.40238,  14.94944,  15.49364,  16.03681,
        16.5498 ,  16.78362,  16.90331,  17.02299,  17.12194,  17.09449,
        17.00066,  16.93006,  16.9723 ,  17.21697,  17.75368])

啊,将字符串设置为文件缓冲区...太棒了。知道那里应该有一些聪明的方法。 - Matt
这与我发布的链接中的第5种方法非常相似,我想我应该注意到它。谢谢。我可能会坚持使用Boud的方法。 - Dan
@Dan,不是很确定,因为我的代码中的所有操作都是在C级别上执行的,所以很可能更快,而且使用numpy函数避免了重复造轮子。 - jamylak

8

如果您想要一些字符串表示(不一定是CSV格式),您可以尝试使用以下代码,这是我一直在使用的:

import numpy, json

## arr is some numpy.ndarray
s = json.dumps(arr.tolist())
arrback = numpy.array(json.loads(s))

它适用于大多数常见的数据类型。


1
+1 这很酷,特别是如果你需要保持精度。 - Dan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接