0

を使用して大きな CSV ファイルを解析していますcsv.DictReader

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

次に、各行について、これを使用して CSV の時刻値を datetime に変換しています。

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日ごとにデータを保存してからアクションを実行する必要がありますか? 解析をベイクする効率的な方法は何でしょうか?

4

3 に答える 3

4

jogojapan が指摘したように、CSV ファイルが日付順にソートされていると想定できるかどうかを知ることが重要です。そうであればitertools.groupby、コードを簡素化するために使用できます。たとえば、次のコードの for ループは、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」のデータが日付順にソートされている場合にのみ機能することに注意してください。

于 2012-04-17T06:39:16.860 に答える
2

(何らかの理由で)入力行が既に date でソートされていると想定できる場合、新しい行の日付が前のものと同じである限り、ローカル コンテナーに 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)

しかし、その仮定を立てることができない場合は、

  • を長いリストに入れ、それを日付でソートしてから、上記のようなアルゴリズムをソートされたリストに適用します
  • または:dictionary日付をキーとして、行のリストを各キーの値として使用して、行を に配置します。次に、そのディクショナリのキーを反復処理して、日付を共有するすべての行にアクセスできます。

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

于 2012-04-17T05:52:04.207 に答える
1

スペース効率を重視しない場合、エレガントな解決策は、キーがあなたの日であり、値がリスト オブジェクトであるディクショナリを作成し、そこに各日のすべての情報を保存することです。後で、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]

は、保存したすべての情報を含む単純なリスト オブジェクトを提供します。ディクショナリの線形ルックアップ時間を考えると、時間の点で非常に効率的です。

于 2012-04-17T06:22:03.800 に答える