2017-08-14 10 views
0

私は、パンダによって読み込まれている一連の非常に乱雑な* .csvファイルを持っています。例のcsvは次のとおりです。pandas.read_csv()内のデータを破棄して、ヘッダ=キーワードを破棄する不正な行を無視します。

Instrument 35392 
"Log File Name : station" 
"Setup Date (MMDDYY) : 031114" 
"Setup Time (HHMMSS) : 073648" 
"Starting Date (MMDDYY) : 031114" 
"Starting Time (HHMMSS) : 090000" 
"Stopping Date (MMDDYY) : 031115" 
"Stopping Time (HHMMSS) : 235959" 
"Interval (HHMMSS) : 010000" 
"Sensor warmup (HHMMSS) : 000200" 
"Circltr warmup (HHMMSS) : 000200" 


"Date","Time","","Temp","","SpCond","","Sal","","IBatt","" 
"MMDDYY","HHMMSS","","øC","","mS/cm","","ppt","","Volts","" 

"Random message here 031114 073721 to 031114 083200" 
03/11/14,09:00:00,"",15.85,"",1.408,"",.74,"",6.2,"" 
03/11/14,10:00:00,"",15.99,"",1.96,"",1.05,"",6.3,"" 
03/11/14,11:00:00,"",14.2,"",40.8,"",26.12,"",6.2,"" 
03/11/14,12:00:01,"",14.2,"",41.7,"",26.77,"",6.2,"" 
03/11/14,13:00:00,"",14.5,"",41.3,"",26.52,"",6.2,"" 
03/11/14,14:00:00,"",14.96,"",41,"",26.29,"",6.2,"" 
"message 3" 
"message 4"** 

私はダブルヘッダーは空の列を引き出し、*のcsvファイルをインポートするには、このコードをプロセスを使用して、不正なデータで、問題のある行を削除されています:

DF = pd.read_csv(BADFILE,parse_dates={'Datetime_(ascii)': [0,1]}, sep=",", \ 
      header=[10,11],na_values=['','na', 'nan nan'], \ 
      skiprows=[10], encoding='cp1252') 

DF = DF.dropna(how="all", axis=1) 
DF = DF.dropna(thresh=2) 
droplist = ['message', 'Random'] 
DF = DF[~DF['Datetime_(ascii)'].str.contains('|'.join(droplist))] 

DF.head() 

Datetime_(ascii) (Temp, øC) (SpCond, mS/cm) (Sal, ppt) (IBatt, Volts) 
0 03/11/14 09:00:00 15.85 1.408 0.74 6.2 
1 03/11/14 10:00:00 15.99 1.960 1.05 6.3 
2 03/11/14 11:00:00 14.20 40.800 26.12 6.2 
3 03/11/14 12:00:01 14.20 41.700 26.77 6.2 
4 03/11/14 13:00:00 14.50 41.300 26.52 6.2 

私は、ヘッダの後にerronious 1行線を持つファイルを持ってまで、これは結構な仕事をしていた:「ランダムなメッセージをここに031114 073721 031114に083200」

を私はreceieveエラーは次のとおりです。

*C:\Users\USER\AppData\Local\Continuum\Anaconda3\lib\site- 
    packages\pandas\io\parsers.py in _do_date_conversions(self, names, data) 
    1554    data, names = _process_date_conversion(
    1555     data, self._date_conv, self.parse_dates, self.index_col, 
    -> 1556     self.index_names, names, 
    keep_date_col=self.keep_date_col) 
    1557 
    1558   return names, data 
    C:\Users\USER\AppData\Local\Continuum\Anaconda3\lib\site- 
    packages\pandas\io\parsers.py in _process_date_conversion(data_dict, 
    converter, parse_spec, index_col, index_names, columns, keep_date_col) 
    2975  if not keep_date_col: 
    2976   for c in list(date_cols): 
    -> 2977    data_dict.pop(c) 
    2978    new_cols.remove(c) 
    2979 
    KeyError: ('Time', 'HHMMSS')* 

その行を削除しても、コードは正常に動作します。同様に、ヘッダー=行を削除すると、コードは正常に動作します。しかし、私はこれらのファイルを何百も読んでいるので、これを保存できるようにしたい。

難易度:私はこれらのファイルはかなり大きくなる可能としてpandas.read_csv()への呼び出しの前に、各ファイルを開かないことを好むだろう - ので、私は何度も読み、保存したくありません!また、私は、違反行を削除するためにstringIOバッファとして最初にファイルを開くことを伴わない実際のパンダ/ピジョンソニックソリューションを好むでしょう。

+0

は、あなたが間違ったラインを投稿することができますか?それはエラーが発生するすべての場合に表示される同じ種類の誤った行ですか、またはいくつかのファイルの他の行に他の種類の問題があるかもしれませんか? –

+0

エラーを生成するエラーが発生した行は次のとおりです。 「ランダムなメッセージはここにあります031114 073721から031114 083200」 この行は、すべてのファイルに存在する場合と存在しない場合があります。したがって、私はskiprows = indexだけを上げることはできません。 また、その行の実際のテキストを変更しても、エラーはそのままです。つまり、テキストが何であるかは関係ありませんが、ヘッダーの後に1列しかない行です。 –

答えて

1

ここには、skip_rowsが呼び出し可能な関数を受け入れるという事実を利用した1つのアプローチがあります。関数は、考慮されている行インデックスのみを受け取ります。これは、そのパラメータのビルトイン制限です。

したがって、呼び出し可能な関数skip_test()は、現在のインデックスがスキップする既知のインデックスのセット内にあるかどうかをまずチェックします。そうでない場合は、実際のファイルを開き、対応する行が一致しているかどうかを確認します。

skip_test()関数は、現在の行インデックスが評価されるまで検査するだけであるにもかかわらず、実際のファイルを検査するという点でちょっとハックリです。また、悪い行は常に同じ文字列(例では"foo")で始まると想定していますが、これはOPを前提とした安全な仮定のようです。

# example data 
""" foo.csv 
uid,a,b,c 
0,1,2,3 
skip me 
1,11,22,33 
foo 
2,111,222,333 
""" 

import pandas as pd 

def skip_test(r, fn, fail_on, known): 
    if r in known: # we know we always want to skip these 
     return True 
    # check if row index matches problem line in file 
    # for efficiency, quit after we pass row index in file 
    f = open(fn, "r") 
    data = f.read() 
    for i, line in enumerate(data.splitlines()): 
     if (i == r) & line.startswith(fail_on): 
      return True 
     elif i > r: 
      break 
    return False 

fname = "foo.csv" 
fail_str = "foo" 
known_skip = [2] 
pd.read_csv(fname, sep=",", header=0, 
      skiprows=lambda x: skip_test(x, fname, fail_str, known_skip)) 
# output 
    uid a b c 
0 0 1 2 3 
1 1 11 22 33 
2 2 111 222 333 

あなたはランダムなメッセージは、それが表示されないときに表示される行かを正確に知っている場合は、あなただけの潜在的な問題、過去の任意のインデックスのファイルの内容を検査しないようにそれを言うことができるように、これは、はるかに高速になりますライン。

+0

ありがとう!はい、私のファイルを通過することによってどのようなメッセージが表示されるのか分かります。そのために解析することができます。 –

+0

あなたはようこそ! –

0

私は解決策を見つけ、潜在的な問題が何であるかを知りました。

私は上記)(skip_test機能答えを試みたが、私はまだ、テーブルのサイズとの誤差を得ていた。

pandas\_libs\parsers.pyx in pandas._libs.parsers.TextReader.read (pandas\_libs\parsers.c:10862)() 

pandas\_libs\parsers.pyx in pandas._libs.parsers.TextReader._read_low_memory (pandas\_libs\parsers.c:11138)() 

pandas\_libs\parsers.pyx in pandas._libs.parsers.TextReader._read_rows (pandas\_libs\parsers.c:11884)() 

pandas\_libs\parsers.pyx in pandas._libs.parsers.TextReader._tokenize_rows (pandas\_libs\parsers.c:11755)() 

pandas\_libs\parsers.pyx in pandas._libs.parsers.raise_parser_error (pandas\_libs\parsers.c:28765)() 

ParserError: Error tokenizing data. C error: Expected 1 fields in line 14, saw 11 

のでのskipRows =で遊んでた後、私は私がしたことを発見エンジン= 'c'を使用したときに、私が望む動作を得られないだけです。 read_csv()は、まだ最初の数行からファイルのサイズを判断していましたが、それらの単一列の行のいくつかは引き続き渡されていました。それは私が計画していない私のCSVセットのいくつかのより悪い単一の列の行があるかもしれないかもしれません。

代わりに、任意のサイズのDataFrameをテンプレートとして作成します。私は.csvファイル全体を引っ張ってから、論理を使ってNaN行を削除します。

たとえば、私は自分のデータで遭遇する最大のテーブルが10行長くなることを知っています。だから、パンダに私の呼び出しは次のとおりです。

DF = pd.read_csv(csv_file, sep=',', \ 
    parse_dates={'Datetime_(ascii)': [0,1]},\ 
    na_values=['','na', '999999', '#'], engine='c',\ 
    encoding='cp1252', names = list(range(0,10))) 

私はその後、データフレームからはNaN行と列を削除するには以下の2行を使用します。

#drop the null columns created by double deliminators 
DF = DF.dropna(how="all", axis=1) 
DF = DF.dropna(thresh=2) # drop if we don't have at least 2 cells with real values 
関連する問題