我想导入两种CSV文件,有的用“;”作为分隔符,其他人则使用“,”。到目前为止,我一直在下面两行之间切换:
reader=csv.reader(f,delimiter=';')
或
reader=csv.reader(f,delimiter=',')
有没有可能不指定这个参数,而让程序检查正确的参数?
下面的解决方案(Blender和sharth)似乎适用于逗号分隔的文件(使用Librooffice生成),但不适用于分号分隔的文件(使用MS Office生成)。以下是一个以分号分隔的文件的第一行:
ReleveAnnee;ReleveMois;NoOrdre;TitreRMC;AdopCSRegleVote;AdopCSAbs;AdoptCSContre;NoCELEX;ProposAnnee;ProposChrono;ProposOrigine;NoUniqueAnnee;NoUniqueType;NoUniqueChrono;PropoSplittee;Suite2LecturePE;Council PATH;Notes
1999;1;1;1999/83/EC: Council Decision of 18 January 1999 authorising the Kingdom of Denmark to apply or to continue to apply reductions in, or exemptions from, excise duties on certain mineral oils used for specific purposes, in accordance with the procedure provided for in Article 8(4) of Directive 92/81/EEC;U;;;31999D0083;1998;577;COM;NULL;CS;NULL;;;;Propos* are missing on Celex document
1999;1;2;1999/81/EC: Council Decision of 18 January 1999 authorising the Kingdom of Spain to apply a measure derogating from Articles 2 and 28a(1) of the Sixth Directive (77/388/EEC) on the harmonisation of the laws of the Member States relating to turnover taxes;U;;;31999D0081;1998;184;COM;NULL;CS;NULL;;;;Propos* are missing on Celex document
6条答案
按热度按时间x3naxklr1#
csv
模块似乎建议使用csv嗅探器来解决这个问题。他们给予了下面的例子,我已经为您的情况进行了调整。
我们来试试
和我们的样本输入
如果我们执行示例程序:
另外,我还需要注意我使用的是什么版本的python。
hxzsmxv22#
给定一个同时处理,(逗号)和|(竖线)分隔的CSV文件,格式良好,我尝试了以下方法(如https://docs.python.org/2/library/csv.html#csv.Sniffer所示):
然而,在A|-delimited文件时,返回“无法确定分隔符”异常。我们有理由推测,如果每一行都有相同数量的分隔符(不包括引号中的分隔符),嗅探启发式算法可能会工作得最好。因此,我没有阅读文件的前1024个字节,而是尝试完整地读取前两行:
到目前为止,这对我来说很好。
oaxa6hgo3#
为了解决这个问题,我创建了一个函数,它读取文件(头)的第一行并检测分隔符。
azpvetkf4#
如果你使用
DictReader
,你可以这样做:我在
Python 3.5
中使用了这个,它是这样工作的。djmepvbi5#
我不认为有一个完美的通用解决方案(我可能使用
,
作为分隔符的原因之一是我的一些数据字段需要能够包含;
...)。一个简单的启发式决定可能是简单地阅读第一行(或更多行),计算它包含多少,
和;
字符(可能忽略引号内的字符,如果创建.csv
文件的任何东西正确且一致地引用条目),并猜测两者中更频繁的是正确的分隔符。dzjeubhm6#
如果csv.Sniffer不符合您的需求,请遵循@twalberg的想法,这里有两种可能的实现来识别正确的分隔符,但不仅仅是检查常见的
,
,;
和|
分隔符,而是普遍识别类csv文件中的任何类型的奇怪分隔符。天真的方法
下面的代码读取csv文件的前10行,获取任何非字母数字字符,并计算频率。
此代码完全基于大数定律,即最常用的非字母数字字符一般应作为分隔符。
当然,如果我们有5列由
|
(4次/行)分隔,但在接下来的9行中的每一行中也有5+.
char,这将打破。{'|': 10*4, '.': 9*5}
不那么幼稚的方法
因此,更好的方法是首先检查和计数标题/第一行中的所有特殊字符,然后在后续行中执行相同的操作。
在识别第一行中的特殊字符之后,然后检查这些字符中,哪一个的频率在其余行中匹配得最多。
继续上面的例子,即使在最坏的情况下,如果我们在标题行中有4个
|
和4个.
,这意味着|
和.
可以作为定界符,通过检查接下来的n
行,通常'|':4
将是最常见的,而.
和其他特殊字符将有所不同。在第一种天真的方法失败的地方,这种方法将起作用。
唯一会失败的情况是,如果另一个特殊字符出现在标题行中,并且也出现在其他行中,与实际定界符字符的次数完全相同:
在这种情况下,
.
与|
一样是有效的分隔符。然而,如果存在甚至一个行,其中计数与标题行中的计数不完全相同,则后一种方法将成功地标识正确的分隔符。因此,增加要检查的行数可能是值得的。需要考虑的其他事项
上述方法假设CSV文件具有标题行。如果文件没有标头,则该方法将第一个数据行视为标头,从而导致分隔符检测中的潜在错误。
另一件经常给我带来问题的事情是文件编码。特别是,如果你在Windows上工作,Excel喜欢用
Windows-1250
编码保存它。因此,请确保在阅读文件时定义了正确的编码。要检测编码,可以使用chardet库。