【问题标题】:Counting number of occurrences up to x days previous to row date计算行日期前 x 天的出现次数
【发布时间】:2013-12-05 06:51:20
【问题描述】:

所以,我一直在尝试编辑此脚本,以定义代码在多少天前开始为每一行工作。

我目前使用的代码:

import csv
import datetime
import copy
from collections import defaultdict

with open(r"C:\Temp\test.csv") as i, open(r"C:\Temp\resuls.csv", "wb") as o:
    rdr = csv.reader(i)
    wrt = csv.writer(o)

    data, currdate = defaultdict(lambda:[0, 0, 0, 0]), None
    for line in rdr:
        date, name = datetime.datetime.strptime(line[0], '%d/%m/%Y'), line[7]

        if date != currdate or not currdate:
            for v in data.itervalues(): v[:2] = v[2:]
            currdate = date

        wrt.writerow(line + data[name][:2])

        data[name][3] += 1
        if line[6] == "1": data[name][2] += 1

适用的数据:

02/01/2005,Data,Class xpv,4,11yo+,4,1,George Smith
02/01/2005,Data,Class xpv,4,11yo+,4,2,Ted James
02/01/2005,Data,Class xpv,4,11yo+,4,3,Emma Lilly
02/01/2005,Data,Class xpv,4,11yo+,4,5,George Smith
02/01/2005,Data,Class tn2,4,10yo+,6,4,Tom Phillips
03/01/2005,Data,Class tn2,4,10yo+,6,2,Tom Phillips
03/01/2005,Data,Class tn2,4,10yo+,6,5,George Smith
03/01/2005,Data,Class tn2,4,10yo+,6,3,Tom Phillips
03/01/2005,Data,Class tn2,4,10yo+,6,1,Emma Lilly
03/01/2005,Data,Class tn2,4,10yo+,6,6,George Smith
04/01/2005,Data,Class tn2,4,10yo+,6,6,Ted James
04/01/2005,Data,Class tn2,4,10yo+,6,3,Tom Phillips
04/01/2005,Data,Class tn2,4,10yo+,6,2,George Smith
04/01/2005,Data,Class tn2,4,10yo+,6,4,George Smith
04/01/2005,Data,Class tn2,4,10yo+,6,1,George Smith
04/01/2005,Data,Class tn2,4,10yo+,6,5,Tom Phillips
05/01/2005,Data,Class 22zn,2,10yo+,5,3,Emma Lilly
05/01/2005,Data,Class 22zn,2,10yo+,5,1,Ted James
05/01/2005,Data,Class 22zn,2,10yo+,5,2,George Smith
05/01/2005,Data,Class 22zn,2,10yo+,5,4,Emma Lilly
05/01/2005,Data,Class 22zn,2,10yo+,5,5,Tom Phillips

并产生:

02/01/2005,Data,Class xpv,4,11yo+,4,1,George Smith,0,0
02/01/2005,Data,Class xpv,4,11yo+,4,2,Ted James,0,0
02/01/2005,Data,Class xpv,4,11yo+,4,3,Emma Lilly,0,0
02/01/2005,Data,Class xpv,4,11yo+,4,5,George Smith,0,0
02/01/2005,Data,Class tn2,4,10yo+,6,4,Tom Phillips,0,0
03/01/2005,Data,Class tn2,4,10yo+,6,2,Tom Phillips,0,0
03/01/2005,Data,Class tn2,4,10yo+,6,5,George Smith,1,2
03/01/2005,Data,Class tn2,4,10yo+,6,3,Tom Phillips,0,0
03/01/2005,Data,Class tn2,4,10yo+,6,1,Emma Lilly,0,1
03/01/2005,Data,Class tn2,4,10yo+,6,6,George Smith,1,2
04/01/2005,Data,Class tn2,4,10yo+,6,6,Ted James,0,1
04/01/2005,Data,Class tn2,4,10yo+,6,3,Tom Phillips,1,2
04/01/2005,Data,Class tn2,4,10yo+,6,2,George Smith,1,4
04/01/2005,Data,Class tn2,4,10yo+,6,4,George Smith,1,4
04/01/2005,Data,Class tn2,4,10yo+,6,1,George Smith,1,4
04/01/2005,Data,Class tn2,4,10yo+,6,5,Tom Phillips,0,3
05/01/2005,Data,Class 22zn,2,10yo+,5,3,Emma Lilly,1,2
05/01/2005,Data,Class 22zn,2,10yo+,5,1,Ted James,0,2
05/01/2005,Data,Class 22zn,2,10yo+,5,2,George Smith,2,7
05/01/2005,Data,Class 22zn,2,10yo+,5,4,Emma Lilly,1,2
05/01/2005,Data,Class 22zn,2,10yo+,5,5,Tom Phillips,0,5

它正在执行以下操作并附加为两个新列:

  1. 计算一个人在行中指定日期之前的日期出现在列表中的次数,并且在第 7 列中出现 1。
  2. 一个人(第 8 列)在行中指定日期之前的日期出现在列表中的次数(请注意,源数据按时间顺序排序。)

目前我的源 CSV 包含多年的历史数据,我需要做的是限制它记住数据的时间。我不确定实现这一点的最佳方法是编辑原始代码还是重新编写整个代码。例如,如果我只想对过去 365 天或过去 60 天执行相同的计数。对实现此目的的方法或编辑有何建议?

【问题讨论】:

  • 将数据放入数据库(例如sqlite)并从那里查询您想要的内容可能更容易。
  • 是的,我最初确实考虑过这一点,但数据操作和标准化的数量导致我将其保留为 csv 格式。
  • 问题是高效并且只从 csv 中加载您需要的内容,还是在 python 中轻松按日期查询的好方法?
  • @RyanSaxe 对不起,Ryan,我不关注?
  • @AEA 你是更关心日期 API 和“Pythonic”的编写方式,还是更不想将这么大的 csv 加载到 python 中?跨度>

标签: python python-2.7 csv collections dictionary


【解决方案1】:

如果你真的不想使用数据库并加载整个 csv,我会使用 pandas 进行这种查询(注意,(可能比 SQL 查询慢得多)

以下是加载 csv 并仅获取最近 60 天的方法:

import pandas as pd
import datetime

today = datetime.date.today()
sixty_days_ago = today - datetime.timedelta(days=60)

df = pd.io.parsers.read_csv("your_csv.csv")
#assume column name is date
condition = (df.date >= sixty_days_ago) & (df.date <= now)

df_between_correct_dates = df[condition]

现在 df_between_correct_dates 将成为 pandas DataFrame,其中仅包含 csv 中日期列中日期不超过 60 天的行!

如果这不能解决您的问题,请告诉我。

【讨论】:

  • 您好 Ryan,我觉得我的 cmets 或原始问题误导了您关于我想要实现的目标。我将在我的问题底部添加更多内容以阐明问题的目标。
  • @AEA 抱歉,我实际上完全忘记了这一点哈哈...看着你的澄清,我仍然不是 100% 确定你想要什么。请在您的代码中评论什么做什么,什么不做什么。我了解您希望与特定时间框架相关,但您是否也想与其他时间做相关的事情?还不是很清楚
【解决方案2】:

如果我正确理解您的要求,您想计算过去 N 天的 1_occurrence(第 7 列)和 name_occurrence(第 8 列)并忽略第 N 天之前的任何数据

由于您希望将搜索限制为 N 天,因此您需要维护日期数据。 如果你这样做,你的脚本仍然可以进行一些调整

你可以这样做

def f5(last_N_days):
    with open("data.csv") as i, open("resuls.csv", "wb") as o:
        rdr = csv.reader(i)
        wrt = csv.writer(o)
        data, currdate = defaultdict(lambda:[0, 0,0,0]), None
        cumulativedata = defaultdict(lambda:defaultdict(lambda:[0, 0,0,0]))
        for line in rdr:
            date, name = datetime.datetime.strptime(line[0], '%d/%m/%Y'), line[7]

            if date != currdate or not currdate:
                for k,v in data.iteritems():
                    cumulativedata[currdate][k] = list(v[2:])
                    v[:2]=[v[2] - cumulativedata[clean_before][k][0],
                                 v[3] - cumulativedata[clean_before][k][1]]
                clean_before = date + datetime.timedelta(days=-(last_N_days))
                currdate = date

            wrt.writerow(line + data[name][:2])

            data[name][3] += 1

            if line[6] == "1":
                data[name][2] += 1

f5(1) # Calculate only for last 1 day

产生以下内容

02/01/2005,Data,Class xpv,4,11yo+,4,1,George Smith,0,0
02/01/2005,Data,Class xpv,4,11yo+,4,2,Ted James,0,0
02/01/2005,Data,Class xpv,4,11yo+,4,3,Emma Lilly,0,0
02/01/2005,Data,Class xpv,4,11yo+,4,5,George Smith,0,0
02/01/2005,Data,Class tn2,4,10yo+,6,4,Tom Phillips,0,0
03/01/2005,Data,Class tn2,4,10yo+,6,2,Tom Phillips,0,1
03/01/2005,Data,Class tn2,4,10yo+,6,5,George Smith,1,2
03/01/2005,Data,Class tn2,4,10yo+,6,3,Tom Phillips,0,1
03/01/2005,Data,Class tn2,4,10yo+,6,1,Emma Lilly,0,1
03/01/2005,Data,Class tn2,4,10yo+,6,6,George Smith,1,2
04/01/2005,Data,Class tn2,4,10yo+,6,6,Ted James,0,0
04/01/2005,Data,Class tn2,4,10yo+,6,3,Tom Phillips,0,2
04/01/2005,Data,Class tn2,4,10yo+,6,2,George Smith,0,2
04/01/2005,Data,Class tn2,4,10yo+,6,4,George Smith,0,2
04/01/2005,Data,Class tn2,4,10yo+,6,1,George Smith,0,2
04/01/2005,Data,Class tn2,4,10yo+,6,5,Tom Phillips,0,2
05/01/2005,Data,Class 22zn,2,10yo+,5,3,Emma Lilly,0,0
05/01/2005,Data,Class 22zn,2,10yo+,5,1,Ted James,0,1
05/01/2005,Data,Class 22zn,2,10yo+,5,2,George Smith,1,3
05/01/2005,Data,Class 22zn,2,10yo+,5,4,Emma Lilly,0,0
05/01/2005,Data,Class 22zn,2,10yo+,5,5,Tom Phillips,0,2

注意: 我假设每个日期都有一个条目。如果这不是真的(如果有任何差距),您可能需要相应地调整脚本

只是一个想法:

如果读取大量历史数据对您造成伤害,那么您可以将读取的 csv 数据限制为 2*N_days (N1...Nn,Nn+1...N2n 其中 Nn+1...N2n 是您的工作块)

提出解决方案here

然后在这个缓冲区中锻炼你的搜索逻辑

【讨论】:

  • v[:2] 之前没有使用过,将算术计算移到循环中以避免每次写入都被计算。请检查上面的更新代码。
  • 我可以让这个脚本与示例完美配合,但是我稍微简化了我的示例。 (不多)但是我无法让这段代码在我的真实脚本中工作。 (出于某种原因)我将尝试在我的问题中应用代码。
  • 请查看我对帖子所做的关于我的问题的编辑。
  • 我可以从您修改后的脚本中了解到,您正在处理标题并为额外的列进行额外的计算。这不应影响其他逻辑。您是否可以共享输入文件以重现问题?
  • 我无法分享确切的输入文件,但我可以创建一个示例。现在就开始吧。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-09
  • 2019-07-06
  • 1970-01-01
  • 2016-05-20
相关资源
最近更新 更多