【问题标题】:split the date range into multiple ranges将日期范围拆分为多个范围
【发布时间】:2020-02-28 01:52:20
【问题描述】:

我有这样的 CSV 数据:

1940-10-01,somevalue
1940-11-02,somevalue
1940-11-03,somevalue
1940-11-04,somevalue
1940-12-05,somevalue
1940-12-06,somevalue
1941-01-07,somevalue
1941-02-08,somevalue
1941-03-09,somevalue
1941-05-01,somevalue
1941-06-02,somevalue
1941-07-03,somevalue
1941-10-04,somevalue
1941-12-05,somevalue
1941-12-06,somevalue
1942-01-07,somevalue
1942-02-08,somevalue
1942-03-09,somevalue

我想将所有数据的日期从 1-oct-year 分隔到 31-march-next-year。所以对于上面输出的数据将是:

1940/1941:

1940-11-02,somevalue
1940-11-03,somevalue
1940-11-04,somevalue
1940-12-05,somevalue
1940-12-06,somevalue
1941-01-07,somevalue
1941-02-08,somevalue
1941-03-09,somevalue

1941/1942:

1941-10-04,somevalue
1941-12-05,somevalue
1941-12-06,somevalue
1942-01-07,somevalue
1942-02-08,somevalue
1942-03-09,somevalue
1942-10-01,somevalue

我的代码轨迹是:

import csv
from datetime import datetime

with open('data.csv','r') as f:
    data = list(csv.reader(f))

quaters = []
year =  datetime.strptime(data[0][0], '%Y-%m-%d').year
for each in data:
    date =  datetime.strptime(each[0], '%Y-%m-%d')
    print(each)        

    if (date>=datetime(year=date.year,month=10,day=1) and date<=datetime(year=date.year+1,month=3,day=31)):
        middle_quaters[-1].append(each)
    if year != date.year:            
        quaters.append([])

但我没有得到预期的输出。我想将每个日期范围存储在单独的列表中。

【问题讨论】:

  • 你的样本结果是不是有错误?为什么 1941/42 年的结果有 1940 年的记录?用正确的输出查看我的答案。
  • @Kaushal28 我刚注意到,是错字。

标签: python python-3.x csv datetime


【解决方案1】:

我会使用pandas dataframe 来执行此操作.. 会更容易.. 按照这个 Pandas: Selecting DataFrame rows between two dates (Datetime Index)

所以你的情况

data = pd.read_csv("data.csv")
df.loc[startDate : endDate]



# you can walk through a bunch of ranges like so..
listOfDateRanges = [(), (), ()]
for date_range in listOfDateRanges:
   df.loc[date_range[0] : date_range[1]]

【讨论】:

  • 但我的日期范围正在发生变化,就像它可以在任何一年一样,所以我无法对其进行硬编码
  • 你在哪里硬编码值?
  • 你的 startDate 和 endDate 可以是你想要的任何东西.. 将它们放在一个列表中.. 作为一个元组.. 并遍历范围以获得所需的日期..
  • @Kaushal28 你是什么意思?它基本上是您传递的过滤参数..
【解决方案2】:

没有外部包...根据选择的字段创建一个查找,然后对其进行 int 并做一个小于与大于建立范围的操作。

import re

data = '''1940-10-01,somevalue
1940-11-02,somevalue
1940-11-03,somevalue
1940-11-04,somevalue
1940-12-05,somevalue
1940-12-06,somevalue
1941-01-07,somevalue
1941-02-08,somevalue
1941-03-09,somevalue
1941-05-01,somevalue
1941-06-02,somevalue
1941-07-03,somevalue
1941-10-04,somevalue
1941-12-05,somevalue
1941-12-06,somevalue
1942-01-07,somevalue
1942-02-08,somevalue
1942-03-09,somevalue'''

lookup={}
lines = data.split('\n')
for line in lines:
    d = re.sub(r'-','',line.split(',')[0])
    lookup[d]=line

dates=sorted(lookup.keys())

_in=19401201
out=19411004
outfile=[]
for date in dates:
    if int(date) > _in and int(date) < out:
        outfile.append(lookup[date])

for l in outfile:
    print outfile

【讨论】:

  • 文件中存储的输入是什么?这不会是首先将csv 转换为字符串然后应用整数运算来确定日期时间范围的优化方法。
【解决方案3】:

为此,您可以使用pandas 库。这是相同的示例代码:

import pandas as pd
df = pd.read_csv('so.csv', parse_dates=['timestamp'])   #timestamp is your time column
current_year, next_year = 1940, 1941
df = df.query(f'(timestamp >= "{current_year}-10-01") & (timestamp <= "{next_year}-03-31")')
print (df)

这会为您的数据提供以下结果:

   timestamp      value
0 1940-10-01  somevalue
1 1940-11-02  somevalue
2 1940-11-03  somevalue
3 1940-11-04  somevalue
4 1940-12-05  somevalue
5 1940-12-06  somevalue
6 1941-01-07  somevalue
7 1941-02-08  somevalue
8 1941-03-09  somevalue

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 2013-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-15
    • 1970-01-01
    相关资源
    最近更新 更多