使用csv.Dictreader处理数据子集

时间:2012-04-17 05:27:36

标签: python csv

我正在使用csv.Dictreader解析一个大的csv文件。

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

然后,对于每一行,我使用以下方法在datetime中转换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循环中执行它,或者我是否可以每天保存数据然后执行操作?什么是烘焙解析的有效方法?

谢谢!

3 个答案:

答案 0 :(得分:4)

正如jogojapan指出的那样,重要的是要知道我们是否可以假设CSV文件按日期排序。如果是,则可以使用itertools.groupby来简化代码。例如,此代码中的for循环在某一天迭代数据:

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”中的数据按日期排序时才会有效。

答案 1 :(得分:2)

如果(由于某种原因)您可以假设输入行已按日期排序,您可以将它们逐个放入本地容器中任何新行的日期与前一行的日期相同:

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 :(得分: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]

将为您提供一个列表对象,其中包含您存储的所有信息。鉴于字典的线性查找时间,它在时间方面应该非常有效。