0

我正在使用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 循环中执行此操作,或者我是否应该每天保存数据然后执行操作?烘焙解析的有效方法是什么?

4

3 回答 3

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

于 2012-04-17T06:39:16.860 回答
2

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

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)

但如果你不能做出这样的假设,你将不得不

  • 要么:将行放在一个长列表中,按日期排序,然后将上述算法应用于排序列表
  • 或者:将行放在 a 中dictionary,使用日期作为键,并将行列表作为每个键的值。然后,您可以遍历该字典的键以访问共享日期的所有行。

这两种方法中的第二种方法会占用更多空间,但它可能允许您在主循环中进行一些特定于日期的处理,因为每当您收到一个已存在日期的新行时,您都可以申请立即进行一些特定于日期的处理,可能避免实际显式存储所有特定于日期的行的需要。这是否可能取决于您对行应用的处理类型。

于 2012-04-17T05:52:04.207 回答
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 回答