如何将包含逗号的字符串的numpy数组保存为CSV文件?

4
tl;dr 答案:不要使用numpy。使用csv.writer代替numpy.savetxt
我是Python和NumPy的新手。保存一个包含逗号的字符串的2D数组到CSV文件似乎不应该那么困难,但我无法按照自己想要的方式完成它。
假设我有一个看起来像这样的数组(由列表嵌套而成):
[['text1, text2', 'text3'],
['text4', 'text5']]

我需要一个 CSV 文件,格式如下(或者不带引号)在 Excel 中显示(竖杠 = 单元格分隔符):
'text1, text2' | 'text3'
'text4'        | 'text5'

我正在使用 numpy.savetxt(filename, array, fmt="%s"),并且我得到了以下的 CSV 输出(带有方括号):

['text1, text2','text3']
['text4','text5']

在Excel中显示如下:

['text1  | text2' | 'text3']
['text4' | 'text5']

我尝试了调整savetxt分隔符参数,但输出没有变化。

我需要手动处理吗?如果是这样,请告诉我是否有任何快捷方式。

最终,我需要将CSV导入Postgresql数据库。我不完全清楚CSV格式需要满足什么条件才能正常工作,但我认为如果在Excel中看起来不对,那么在Postgres中可能会出现问题。Postgres documentation中写道:

每条记录中的值由DELIMITER字符分隔。如果该值包含分隔符字符、QUOTE字符、NULL字符串、回车或换行符,则整个值将由QUOTE字符前缀和后缀,并且该值内部的任何QUOTE字符或ESCAPE字符的出现都将被转义字符所代替。您还可以使用FORCE_QUOTE来强制引用特定列中输出的非NULL值。

谢谢!

++++++++++++++++++++++++++++

真实的输入和输出,如果相关差异很大:

数组:

[['8908232', 'Plant Growth Chamber Facility at the Department of Botany, University of Wisconsin-Madison', 'DBI', 'INSTRUMENTAT & INSTRUMENT DEVP', '1/1/90', '12/19/89', 'WI', 'Standard Grant', 'Joann P. Roskoski', '12/31/91', '$94,914.00 ', 'BIO', '1108', '', '$0.00 ']]

CSV输出:

['8908232', 'Plant Growth Chamber Facility at the Department of Botany, University of Wisconsin-Madison', 'DBI', 'INSTRUMENTAT & INSTRUMENT DEVP', '1/1/90', '12/19/89', 'WI', 'Standard Grant', 'Joann P. Roskoski', '12/31/91', '$94,914.00 ', 'BIO', '1108', '', '$0.00 ']

Excel的版本:

['8908232'   'Plant Growth Chamber Facility at the Department of Botany  University of Wisconsin-Madison'    'DBI'   'INSTRUMENTAT & INSTRUMENT DEVP'    '1/1/90'    '12/19/89'  'WI'    'Standard Grant'    'Joann P. Roskoski'     '12/31/91'  '$94   914.00 '     'BIO'   '1108'  ''  '$0.00 ']                  

1
这可能是 Python 擅长的事情之一,而不是 NumPy 擅长的事情之一。标准库中的 csv 模块旨在处理各种 CSV 文件中的字符串写入和解析,支持每种合理的 CSV 方言。np.savetxt 旨在将数值数组写入到简单的 CSV 方言中... - abarnert
此外,您并没有为该代码获得输出。请向我们展示您的实际代码和实际输出,否则我们无法告诉您实际出错的地方。 - abarnert
在上面添加了实际输出并进一步澄清了问题。实验室里有人向我推荐了Numpy.savetxt,但你说得对,csv.writer更好。 - ems
你的CSV输出每行都有括号,是这样吗?那么你有一个更大的问题。显然,你没有一个二维数组,而是一个由list对象组成的一维数组,NumPy只是将它们视为标量对象并打印出它们的str,这不是你想要的。但是,无论如何,你并没有你所问的问题,所以我不知道你为什么在问这个问题。如果你想解决真正的问题,请提出一个新的问题。如果解决这个问题恰好会引起你所问的问题(我认为不会,但可能会),请回来。 - abarnert
我不确定你认为我在问什么问题,但我确实遇到了一个问题,并尽可能详细地描述了我的问题 - 我根据您的反馈添加了一些上下文并更改了标题。对于最初关于管道的混淆,我感到抱歉。事实证明,您帮助我解决了我的问题。使用csv.write()而不是numpy.savetxt()给了我想要的输出。所以,感谢您回答了我可能没有提出的问题 :) - ems
1个回答

6

fmt="%s"添加到代码中不会在每个字段周围添加引号——引号是Python字符串文字的一部分,用于字符串%s,而%s只是表示任何值都应该被格式化为字符串。如果您想强制在所有内容周围加上引号,则需要在格式字符串中添加引号,例如fmt='"%s"'

然而,即使您不这样做,您展示的行也不可能产生您展示的输出。NumPy不可能将逗号更改为竖线字符或使用竖线字符作为分隔符。唯一可以做到这一点的方法是添加delimiter=' |' 。如果您添加了这个参数,它将无需进行任何更改即可正常工作,您将得到以下输出:

text1, text2 | text3
text4 | text5

所以无论你实际的问题是什么,它都不可能是你描述的那个。


同时,如果你想尽可能灵活地为非数值数据编写CSV文件,标准库的csv模块比NumPy强大得多。NumPy的优势正如其名称所示,处理的是数字数据。这是如何使用csv

with open(filename, 'wb') as f:
    csv.writer(f).writerows(array)

这将以,作为分隔符的默认设置。由于你的某些字符串中包含,字符,因此默认情况下,它会引用这些字符串。但是你可以配置引用/转义行为,引号字符、分隔符和NumPy无法处理的各种其他事情。


为什么 fmt='%s' 是默认值?它应该是 fmt='%.18e',因此 OP 的 fmt 参数不仅影响输出,而且是必需的(对于字符串数组)。 - askewchan
@askewchan:你说得对,我以为默认值是特定于dtype的,但实际上不是。我会进行编辑。但问题在于,它不能做到他想要的,也就是在字段周围添加引号。 - abarnert
@askewchan:当然,这忽略了他现有的代码根本没有他要我们解决的问题,所以我不确定为什么我们要试图回答它... - abarnert
1
哈哈,没错。也许楼主并不想在输出中使用管道符,而是用它来表示分隔符的位置? - askewchan
@askewchan 是正确的 - 我之前是用管道来查看CSV文件(因为我是在Excel中查看)。我已经更改了问题以更好地反映CSV格式。 - ems
显示剩余2条评论

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