2012-04-17 7 views
0

私はcsv.Dictreaderを使用して大きなcsvファイルを解析しています。csv.Dictreaderを使用してデータのサブセットを扱う

quotes=open("file.csv", "rb") 
csvReader= csv.DictReader(quotes) 

はその後、行ごとに、私はこれを使用して日時でcsvファイルで時刻値を変換しています:

for data in csvReader: 
    year = int(data["Date"].split("-")[2]) 
    month = strptime(data["Date"].split("-")[1],'%b').tm_mon 
    day = int(data["Date"].split("-")[0]) 
    hour = int(data["Time"].split(":")[0]) 
    minute = int(data["Time"].split(":")[1]) 

    bars = datetime.datetime(year,month,day,hour,minute) 

今、私は唯一の同じ日の行に対してアクションを実行したいと思います 。同じforループで実行することは可能でしょうか、またはデータを1日に保存してからアクションを実行する必要がありますか?解析をベーキングする効率的な方法は何でしょうか?

ありがとうございました!

+1

FYIのすべての変換は 'bars = datetime.datetime.strptime(data ['Date'] + data ['Time']、 '%d-%b-%Y%H:%M')とすることができます(サンプルが提供されていないので、フォーマットに調整が必要な場合があります) –

答えて

3

jogojapanが指摘しているように、CSVファイルが日付でソートされていると判断できるかどうかを知ることが重要です。そうであれば、itertools.groupbyを使用してコードを簡略化することができます。例えば、一度にデータを1日以上、このコードの繰り返し処理のループのために:

import csv 
import datetime 
import itertools 

with open("file.csv", "rb") as quotes: 
    csvReader = csv.DictReader(quotes) 

    lmb = lambda d: datetime.datetime.strptime(d["Date"], "%d-%b-%Y").date() 
    for k, g in itertools.groupby(csvReader, key = lmb): 
     # do stuff per day 
     counts = (int(data["Count"]) for data in g) 
     print "On {0} the total count was {1}".format(k, sum(counts)) 

私は、次のデータを含むテスト「file.csvになり」を作成しました:

Date,Time,Count 
1-Apr-2012,13:23,10 
2-Apr-2012,10:57,5 
2-Apr-2012,11:38,23 
2-Apr-2012,15:10,1 
3-Apr-2012,17:47,123 
3-Apr-2012,18:21,8 

と私は走りました

On 2012-04-01 the total count was 10 
On 2012-04-02 the total count was 29 
On 2012-04-03 the total count was 131 

しかし、「file.csvになり」内のデータを日付でソートされている場合にのみ動作することを覚えておいてください:上記のコードは、私は以下の結果を得ました。

+0

はい、申し訳ありませんが、私はcsvファイルがソートされていることを述べておくべきです –

+0

これは非常にうまく動作しています:) –

2

(何らかの理由で)あなたは、入力行がすでに日付によって並べ替えられて、あなたがいる限り、新しい行の日付が同じであるように、1つによってローカルコンテナ1にそれらを置くことができることをとることができる場合前回と:

same_date_rows = [] 
prev_date  = None 
for data in csvReader: 
    # ... your existing code 
    bars = datetime.datetime(year,month,day,hour,minute) 

    if bars == prev_date: 
    same_date_rows.append(data) 
    else: 
    # New date. We process all rows collected so far 
    do_something(same_date_rows) 
    # Then we start a new collection for the new date 
    same_date_rows = [date] 

    # Remember the date of the current row 
    prev_date = bars 

# Finally, process the final group of rows 
do_something(same_date_rows) 

しかし、あなたはその仮定を作ることができない場合、あなたは

  • EITHする必要がありますER:日付でソートという、長いリスト内の行を入れて、その後、ソートされたリストに上記のようなアルゴリズムを適用
  • または:キーとして日付を使用して、dictionary内の行を入れて、各キーの値としての行のリスト次に、その辞書のキーを繰り返して日付を共有するすべての行にアクセスできます。

これらの2つのアプローチのうちの2つ目は、もう少しスペースを消費しますが、メインループの日付固有の処理のいくつかを行うことができます。実際にすべての日付固有の行を明示的に明示的に格納する必要性を避けるために、日付固有の処理の一部をすぐに適用することができます。それが可能かどうかは、行に適用する処理の種類によって異なります。

+0

第3の解決策は、sqliteデータベースにデータを入れることです –

+0

これもまた役に立ちます。ありがとうございました –

1

space efficenyに向かない場合、エレガントなソリューションは、キーがあなたの日であり、値がリストオブジェクトであり、毎日のすべての情報が格納される辞書を作成することです。後で、1日あたりの操作に応じて何でもできます。

これは、日ごとに新しいリストオブジェクトを変更または作成するか

d = {} #Initialize emptry dictionry 
for data in csvReader: 
Day = int(data["Date"].split("-")[0]) 
    try: 
     d[Day].append('Some_Val') 
    except KeyError: 
     d[Day] = ['Some_val'] 

たとえば。これは後で辞書に反復するか、単にその日をキーとして参照することで簡単にアクセスできます。例えば

d[Some_Day] 

はあなたが保存されているすべての情報を簡単にリストオブジェクトを提供します。辞書のリニアルックアップ時間を考えると、それは時間に関してかなり効率的でなければならない。

+0

このアイデアは、明快さと細部のため+1。 1つの発言:辞書ルックアップは実際には最悪の場合に線形になる可能性がありますが、それはあまり効率的ではありません。私はあなたが "辞書の_定数-1ルックアップ時間"と言いたいと思う。 – jogojapan

+0

はい、私はO(1)と言うつもりでしたが、私がO(n)に行った最悪の場合を満たすためだけでした。それを明確に述べてくれてありがとう。 – subiet

関連する問題