【问题标题】:Does "len" of a list get recalculated in every iteration of a for loop?列表的“len”是否会在 for 循环的每次迭代中重新计算?
【发布时间】:2018-04-26 03:11:52
【问题描述】:

我需要删除日期在 2000 年之前的数据框的所有列。

一般做法是:

columnstokeep = list(DF) #gives me the column names

    for i in range(len(columnstokeep)): #get rid of dates before year 2000
        if int(columnstokeep[i][:4])<2000:
            columnstokeep.remove(columnstokeep[i])

DF = DF[columnstokeep]  #the new dataframe

我一直遇到列表索引超出范围错误。

这是因为每次我删除列表中的一个元素时 len, in range(len(columnstokeep)) 都会发生变化吗?还是 range(len(columnstokeep)) 在循环期间保持相同的值?

这是数据框

谢谢

【问题讨论】:

  • 你能举一个数据框的例子吗?
  • 你可能想要“for i in range(len(columnstokeep)-1)”
  • 在迭代列表时为什么不应该更改列表长度有多个重复项。而是重建列表。但它们与 pandas 并不真正相关,因为首先应该需要像这样进行迭代。你能举个 df 的例子吗?

标签: python pandas


【解决方案1】:

您可以在列上使用pd.to_datetimes 轻松完成此操作,然后选择大于2000 的列。

# Create Example Data
frame = pd.DataFrame({
    '1998-1-1': ['foo'],
    '1999-1-1': ['bar'],
    '2000-1-1': ['spam'],
    '2001-1-1': ['eggs']
})

# Select columns which are after 2000
frame.loc[:,pd.to_datetime(frame.columns) >= '2000']

输出:

  2000-1-1 2001-1-1
0     spam     eggs

【讨论】:

    【解决方案2】:

    您对问题根源的看法是正确的。但我不认为范围会被重新计算。但是由于您从列表中删除第一个值i 将超出剩余的columnstokeep。我添加了一些打印以更清楚地显示问题:

    years = range(1990,2010) 
    columnstokeep=[]
    #The column names kind of
    for i in years:
        columnstokeep.append(str(i)+'-01')
    
    ##This shows the error comment this
    for i in range(len(columnstokeep)-1): #get rid of dates before year 2000
        print(i,columnstokeep[i])#It prints every second year while in 199X
    
        if int(columnstokeep[i][:4])<2000:
            columnstokeep.remove(columnstokeep[i])
    

    相反,您可以从结束迭代到开始......

    for i in range(len(columnstokeep)-1,-1,-1): #get rid of dates before year 2000
        print(i,columnstokeep[i])#It prints every second year while in 199X
    
        if int(columnstokeep[i][:4])<2000:
            columnstokeep.remove(columnstokeep[i])
    
    
    
    #DF = DF[columnstokeep]  #the new dataframe
    print(columnstokeep)
    

    输出:

    ['2000-01', '2001-01', '2002-01', '2003-01', '2004-01', '2005-01', '2006-01', '2007-01', '2008-01', '2009-01']
    

    【讨论】:

    • 您能否向我解释一下为什么在我们迭代时它会在达到 2000 年之前跳过所有其他元素?谢谢。
    • 啊——明白了! @ columnstokeep[0],该值被删除。所以如果列表的长度减少了,它就会跳到columnstokeep[1],但是有一个新的columnstokeep[0]被忽略了。
    • @ZakS 感谢您的支持。我添加了更多的解释。
    • 啊,是的,当然,范围 len 不是问题的根源,这是向上迭代时迭代器跳过一个元素。终于到了。感谢您的明确解释。
    猜你喜欢
    • 1970-01-01
    • 2011-11-08
    • 2012-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-20
    相关资源
    最近更新 更多