2013-05-01 3 views
40

2種類のCSVファイルをインポートしたいのですが、 ";"デリミタなどの場合は "、"を使用します。これまでのところ私は、次の2行の間で切り替えされています:CSVファイルをインポートして区切り文字を自動的に推測できますか?

reader=csv.reader(f,delimiter=';') 

または

reader=csv.reader(f,delimiter=',') 

はそれが区切り文字を指定すると右の区切りのためのプログラムチェックをさせないようにすることができますか?

以下のソリューション(Blenderとsharth)は、カンマ区切りのファイル(Librofficeで生成)では有効ですが、セミコロンで区切られたファイル(MS Officeで生成されたファイル)ではうまく動作しないようです。ここでは1セミコロン区切りファイルの最初の行は、次のとおりです。

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 
+0

こんにちは、より一般的な議論(非pythonで)https://stackoverflow.com/questions/2789695/how-to-programmatically-guess-whether-a-csv-file-is-comma-or-セミコロン区切り – Lorenzo

答えて

6

問題を解決するために、ファイル(ヘッダー)の最初の行を読み取り、区切り文字を検出する関数を作成しました。

+5

区切り文字が括られていたり、引用符で囲まれていても、区切り文字が値の一部であれば、関数は機能しません。たとえば、「こんにちはPeter」、「どうですか?」、「Bye John!」のような行は区切り文字として返されますが、これは間違っています。 – tashuhka

42

csvモジュールは、この問題のためにcsv snifferを使用することをお勧めしているようです。

これらは、次の例を示しています。

with open('example.csv', 'rb') as csvfile: # python 3: 'r',newline="" 
    dialect = csv.Sniffer().sniff(csvfile.read(1024), delimiters=";,") 
    csvfile.seek(0) 
    reader = csv.reader(csvfile, dialect) 
    # ... process CSV file contents here ... 

のは、それを試してみましょう。

[9:13am][[email protected] /tmp] cat example 
#!/usr/bin/env python 
import csv 

def parse(filename): 
    with open(filename, 'rb') as csvfile: 
     dialect = csv.Sniffer().sniff(csvfile.read(), delimiters=';,') 
     csvfile.seek(0) 
     reader = csv.reader(csvfile, dialect) 

     for line in reader: 
      print line 

def main(): 
    print 'Comma Version:' 
    parse('comma_separated.csv') 

    print 
    print 'Semicolon Version:' 
    parse('semicolon_separated.csv') 

    print 
    print 'An example from the question (kingdom.csv)' 
    parse('kingdom.csv') 

if __name__ == '__main__': 
    main() 

そして、我々のサンプル入力

[9:13am][[email protected] /tmp] cat comma_separated.csv 
test,box,foo 
round,the,bend 

[9:13am][[email protected] /tmp] cat semicolon_separated.csv 
round;the;bend 
who;are;you 

[9:22am][[email protected] /tmp] cat kingdom.csv 
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 

そして、我々は例のプログラム実行した場合:

[9:14am][[email protected] /tmp] ./example 
Comma Version: 
['test', 'box', 'foo'] 
['round', 'the', 'bend'] 

Semicolon Version: 
['round', 'the', 'bend'] 
['who', 'are', 'you'] 

An example from the question (kingdom.csv) 
['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'] 

をそれはおそらく私が使用しているのpythonのバージョンは注目に値します。私はこれを完全に一般解(区切り文字は私のデータフィールドの一部が;を含めることができるようにする必要があるということであると私は,を使用するかもしれない理由の一つが存在することができるとは思わない

[9:20am][[email protected] /tmp] python -V 
Python 2.7.2 
+0

カンマ区切りファイルでは機能しますが、セミコロン区切りファイルは正しく読み取れません(区切り文字を判別できませんでした)。上の私の編集を参照してください... – rom

+0

それは私のために動作するようです。私は答えを広げます。 –

+0

私は、コンマ区切り、セミコロン区切り、および質問で提案するサンプルファイルを含むサンプルを含めました。 –

2

... )。単純なヒューリスティックは、最初の行(またはそれ以上)を読み込み、.csvファイルの引用符エントリが正しく一貫して作成されている場合は、引用符を無視して,;の文字を数えます。 2つのうちのより頻繁なものが正しい区切り文字です。

7

このプロジェクトでは、(コンマ)と| (垂直バー)も形成されているCSVファイルを、区切り(https://docs.python.org/2/library/csv.html#csv.Snifferで与えられるように)、私は次のことを試してみました:

dialect = csv.Sniffer().sniff(csvfile.read(1024), delimiters=',|') 

しかし、上| -delimitedファイル、「区切り文字を判別できませんでした」例外が返されました。スニフィルヒューリスティックは、各行に同じ数の区切り文字がある場合(引用符で囲まれているものは数えません)、スニファヒューリスティックが最も効果的であると推測するのは合理的です。だから、代わりに、ファイルの最初の1024のバイトを読んで、私はそれらの全体が最初の二行読んでみました:

temp_lines = csvfile.readline() + '\n' + csvfile.readline() 
dialect = csv.Sniffer().sniff(temp_lines, delimiters=',|') 

をこれまでのところ、これは私のためにうまく機能しています。

+2

これは私にとってとても役に立ちました!私は、 "釘付け"された値の1つがカンマの付いた数字だったので、失敗し続けたというデータに問題がありました。これは最初の2行に限定されているので、本当に助けになりました。 – mauve

+0

私の分かれた "csv"ファイルでうまくやってくれました。ありがとう:) – EisenHeim

6

そして、あなたは、あなたがそれを行うことができDictReaderを使用している場合:

#!/usr/bin/env python 
import csv 

def parse(filename): 
    with open(filename, 'rb') as csvfile: 
     dialect = csv.Sniffer().sniff(csvfile.read(), delimiters=';,') 
     csvfile.seek(0) 
     reader = csv.DictReader(csvfile, dialect=dialect) 

     for line in reader: 
      print(line['ReleveAnnee']) 

私はPython 3.5でこれを使用し、それがこのように働きました。

+1

私はそれをPython 2.7で使用しました – alvaro562003

関連する問題