从python

时间:2016-01-02 07:06:40

标签: python date csv

我正在尝试从大型CSV文件中删除特定日期内具有特定ID的行。

CSV文件包含一列[3],日期格式为“1962-05-23”,列包含标识符[2]:“ddd:011232700:mpeg21:a00191”。

在以下日期范围内:

  • 01-01-1951至12-31-1951
  • 07-01-1962至12-31-1962
  • 01-01至09-30-1963
  • 7-01至07-31-1965
  • 10-01至10-31-1965
  • 04-01-1966至11-30-1966
  • 01-01-1969至12-31-1969
  • 01-01-1970至12-31-1989

我想删除包含ID ddd:11 *

的行

我想我必须创建一个包含日期范围和ID的变量。并且在每一行中寻找这些,但我对python非常新,所以我不确定这样做的雄辩方式。

这就是我现在所拥有的。 - CODE UPDATED

import csv
import collections
import sys
import re
from datetime import datetime

csv.field_size_limit(sys.maxsize)

dateranges = [("01-01-1951","12-31-1951"),("07-01-1962","12-31-1962")]
dateranges = list(map(lambda dr: tuple(map(lambda x: datetime.strptime(x,"%m-%d-%Y"),dr)),dateranges))


def datefilter(x):
    x = datetime.strptime(x,"%Y-%m-%d")
    for r in dateranges:
        if r[0]<=x and r[1]>=x: return True
    return False

writer = csv.writer(open('filtered.csv', 'wb'))
for row in csv.reader('my_file.csv', delimiter='\t'):
    if datefilter(row[3]):
        if not row[2].startswith("dd:111"):
            writer.writerow(row) 
    else: 
        writer.writerow(row)
writer.close()

4 个答案:

答案 0 :(得分:1)

以下是我将采用的方法,但它可能不是最好的方法。

from datetime import datetime
dateranges = [("01-01-1951","12-31-1951"),("07-01-1962","12-31-1962")]
dateranges = list(map(lambda dr: tuple(map(lambda x: datetime.strptime(x,"%m-%d-%Y"),dr)),dateranges))

def datefilter(x):
    # The date format is different here to match the format of the csv
    x = datetime.strptime(x,"%Y-%m-%d")
    for r in dateranges:
        if r[0]<=x and r[1]>=x: return True
    return False

with open(main_file, "rb") as fp:
    root = csv.reader(fp, delimiter='\t')
    result = collections.defaultdict(list)
    for row in root:
        if datefilter(row[3]):
            # use a regular expression or any other means to filter on id here
            if row[2].startswith("dd:111"): #code to remove item

我所做的是创建日期范围的元组列表(为简洁起见,我只在其中放入2个范围),然后将其转换为日期时间对象。

我已经在一行中使用了map:首先遍历该列表中的所有元组,应用一个循环遍历该元组中所有条目的函数并转换为日期时间,使用元组和列表函数返回到原来的结构。从长远来看,它看起来像:

dateranges2=[]
for dr in dateranges:
    dateranges2.append((datetime.strptime(dr[0],"%m-%d-%Y"),datetime.strptime(dr[1],"%m-%d-%Y"))
dateranges = dateranges2

请注意,我只是将元组中的每个项目转换为日期时间,并将元组添加到新列表中,替换原始文件(我不再需要)。

接下来,我创建一个datefilter函数,它接受一个日期字符串,将其转换为日期时间,然后遍历所有范围,检查该值是否在该范围内。如果是,我们返回True(表示此项应该被过滤),否则如果我们检查了所有不匹配的范围,则返回False(表示我们不过滤此项)。

现在,您可以在日期匹配后使用您想要的任何方法检出ID,并根据需要删除该项目。由于您的示例在前几个字符中是常量,我们可以使用字符串startswith函数来检查id。如果它更复杂,我们可以使用正则表达式。

答案 1 :(得分:1)

我建议使用pandas:它非常适合过滤表格。很好,可读。

import pandas as pd

# assumes the csv contains a header, and the 2 columns of interest are labeled "mydate" and "identifier"
# Note that "date" is a pandas keyword so not wise to use for column names
df = pd.read_csv(inputFilename, parse_dates=[2])  # assumes mydate column is the 3rd column (0-based)

df = df[~df.identifier.str.contains('ddd:11')]  # filters out all rows with 'ddd:11' in the 'identifier' column
# then filter out anything not inside the specified date ranges:
df = df[((pd.to_datetime("1951-01-01") <= df.mydate) & (df.mydate <= pd.to_datetime("1951-12-31"))) |
        ((pd.to_datetime("1962-07-01") <= df.mydate) & (df.mydate <= pd.to_datetime("1962-12-31")))]

df.to_csv(outputFilename)

请参阅Pandas Boolean Indexing

答案 2 :(得分:0)

我的方法就是这样 -

import csv 
import re
import datetime

field_id = 'ddd:11'




d1 = datetime.date(1951,1,01) #change the start date
d2 = datetime.date(1951,12,31) #change the end date
diff = d2 - d1
date_list = []
for i in range(diff.days + 1):
    date_list.append((d1 + datetime.timedelta(i)).isoformat())
with open('mwevers_example_2016.01.02-07.25.55.csv','rb') as csv_file:

    reader = csv.reader(csv_file)

    for row in reader:

        for date in date_list:
            if row[3] == date:
                print row
                var = re.search('\\b'+field_id,row[2])
                if bool(var) == True:

                    print 'olalala'#here you can make a function to copy those rows into another file or any list

答案 3 :(得分:0)

import csv
import sys
import re
from datetime import datetime

csv.field_size_limit(sys.maxsize)

field_id = 'ddd:11'

dateranges = [("1951-01-01", "1951-12-31"),
              ("1962-07-01", "1962-12-31"),
              ("1963-01-01", "1963-09-30"),
              ("1965-07-01", "1965-07-30"),
              ("1965-10-01", "1965-10-31"),
              ("1966-04-01", "1966-11-30"),
              ("1969-01-01", "1989-12-31")
              ]
dateranges = list(map(lambda dr:
                      tuple(map(lambda x:
                            datetime.strptime(x, "%Y-%m-%d"), dr)),
                      dateranges))


def datefilter(x):
    x = datetime.strptime(x, "%Y-%m-%d")
    for r in dateranges:
        if r[0] <= x and r[1] >= x:
            return True
    return False


output = []
with open('my_file.csv', 'r') as f:
    reader = csv.reader(f, delimiter='\t', quotechar='"')
    next(reader)
    for row in reader:
        if datefilter(row[4]):
            var = re.search('\\b'+field_id, row[3])
            if bool(var) == False:
                output.append(row)
        else:
            output.append(row)


with open('output.csv', 'w') as outputfile:
    writer = csv.writer(outputfile, delimiter='\t', quotechar='"')
    writer.writerows(output)