【问题标题】:How can I remove datetime elements of a list outside of a specified startdate and enddate period?如何在指定的开始日期和结束日期期间删除列表的日期时间元素?
【发布时间】:2021-07-19 08:10:27
【问题描述】:

我有一个名为“日期”的日期时间对象列表,我正在尝试删除列表中在开始日期和结束日期之外的元素。谁能帮我理解如何正确地做到这一点,以及为什么我得到这个列表索引超出范围错误?我觉得我很接近!

我的代码:

startDate = datetime.strptime('1948-1-1',"%Y-%m-%d")
endDate = datetime.strptime('1950-2-1',"%Y-%m-%d")

for row in range(0,len(date)):
  if date[row] < startDate:
    del date[row]
  elif date[row] > endDate:
    del date[row]

我也尝试了以下方式,它运行但不删除列表元素:

count = 0

for row in date:
  if row < startDate:
    del date[count]
  elif row > endDate:
    del date[count]
  count += 1

【问题讨论】:

    标签: python list datetime indexing del


    【解决方案1】:

    当您遍历列表并删除相同的列表时,这会将其排除在索引之外。想一想,您正在循环遍历 len(list) 但列表的长度与删除的某些条目的长度不同。

    所以列表理解在这里可能会有所帮助,请注意我将 > 和

    from datetime import datetime
    # datasetup
    date=['1947-01-01','1948-01-01','1948-02-02','1951-01-01']
    date=[datetime.strptime(each,"%Y-%m-%d") for each in date]
    #Control date
    startDate = datetime.strptime('1948-1-1',"%Y-%m-%d")
    endDate = datetime.strptime('1950-2-1',"%Y-%m-%d")
    #list comprehension
    date = [each for each in date if  each >= startDate and each <= endDate ]
    

    采取进一步的解决方案,从谷歌驱动器下载数据,使用熊猫过滤所需的数据,然后将其绘制以进行分析。 第 1 步- 下载数据

    import pandas as pd
    import requests
    from io import StringIO
    
    gd_url='https://drive.google.com/file/d/1N2J136mog2CZK_XRyL3pxocaoUV8DByS/view?usp=sharing'
    file_id = gd_url.split('/')[-2]
    download_url='https://drive.google.com/uc?export=download&id=' + file_id
    url = requests.get(download_url).text # get the file
    csv_raw = StringIO(url)
    df = pd.read_csv(csv_raw)
    print(df.head(1))
    

    第 2 步:过滤数据

    #Control date
    startDate = '1948-01-01'
    endDate = '1950-02-01'
    df_new=df.loc[(df['DATE'] >= startDate) & (df['DATE'] <= endDate)] # as doing string compare, make sure that 
    #data looks okay otherwise change it to date for comparision
    

    第 3 步:显示图表。

    import pandas as pd
    import matplotlib.pyplot as plt
    df_new.plot()
    plt.show() 
    

    【讨论】:

    • 你先生是天赐之物。正是我想要的。谢谢你解释得这么好,它帮助我理解了。
    • 很高兴它有帮助。非常欢迎瑞恩!
    • simpleApp,我有另一个关于这个解决方案的问题,说我有另一个列表/列,它与我们在上面的解决方案中保留的日期相对应。我怎样才能得到该列表的相应值,以便我可以使用 pyplot 或类似的东西沿着 y 轴绘制它们,x 轴上的日期?这是我正在使用的 csv 文件:drive.google.com/file/d/1N2J136mog2CZK_XRyL3pxocaoUV8DByS/…
    • 如果我做对了,请在解决方案中添加更多注释。
    【解决方案2】:

    这是一个与你的问题相同的类似 sn-p 代码。

    numbers = list(range(10))
    
    for i in range(len(numbers)):
        if numbers[i] < 3:
            del numbers[i]
        elif numbers[i] > 7:
            del numbers[i]
    
    

    问题在于 range(len(numbers)) 是在循环开始时创建的,它没有注意到 numbers 的长度在迭代时发生了变化。

    这可以通过 while 循环来解决:

    numbers = list(range(10))
    
    i = 0
    while i < len(numbers):
        if numbers[i] < 2:
            del numbers[i]
        elif numbers[i] > 7:
            del numbers[i]
        else:
            i += 1
    
    print(numbers)
    

    注意i只有在没有从列表中删除的情况下才会增加,因为如果说索引1被删除,那么索引2中的项目将向左移动以填补空白,所以索引@987654328 @需要再次检查。

    然而,这个解决方案很冗长,不是很 Pythonic,而且效率很低(O(n^2) 复杂性,因为从列表中删除一个项目是O(n),它可能会完成n 次)。 我建议您使用列表推导来过滤如下值:

    numbers = list(range(10))
    
    print([number for number in numbers if 2 <= number <= 7])
    

    或者,如果循环内需要更复杂的计算,您可以追加到一个新列表(O(n) 总复杂度):

    numbers = list(range(10))
    new_numbers = []
    for i in range(len(numbers)):
        do_delete = False
        if numbers[i] < 2:
            do_delete =True
        elif numbers[i] > 7:
            do_delete = True
    
        if not do_delete:
            new_numbers.append(numbers[i])
    
    print new_numbers
    

    或者您可以使用生成器函数(也可以使用 O(n)):

    numbers = list(range(10))
    
    def my_filter(numbers):
        for i in range(len(numbers)):
            do_delete = False
            if numbers[i] < 2:
                do_delete = True
            elif numbers[i] > 7:
                do_delete = True
    
            if not do_delete:
                yield numbers[i]
    
    print(list(my_filter(numbers)))
    

    【讨论】:

      【解决方案3】:

      使用下面的示例代码

      from datetime import datetime
      
      
      startDate = datetime.strptime('1948-1-1',"%Y-%m-%d")
      endDate = datetime.strptime('1950-2-1',"%Y-%m-%d")
      
      
      date_list = []
      
      date_list.append( datetime.strptime('1949-1-1',"%Y-%m-%d"))
      date_list.append( datetime.strptime('1949-2-1',"%Y-%m-%d"))
      date_list.append( datetime.strptime('1949-2-3',"%Y-%m-%d"))
      date_list.append( datetime.strptime('1950-2-3',"%Y-%m-%d"))
      date_list.append( datetime.strptime('1950-2-1',"%Y-%m-%d"))
      date_list.append( datetime.strptime('1999-2-1',"%Y-%m-%d"))
      date_list.append( datetime.strptime('1993-2-1',"%Y-%m-%d"))
      date_list.append( datetime.strptime('1995-2-1',"%Y-%m-%d"))
      
      
      new_list = copy.deep_copy(date_list)
      
      for idx, date in enumerate(ll):
          if not date < startDate or not date > endDate:
              new_list.append(date)
              
      
      print(new_list)
      

      【讨论】: