有没有一种有效的方法来绕过嵌套的for循环?

时间:2019-02-19 22:01:17

标签: python

我有一个嵌套的for循环,我想知道是否有更有效的方法来实现此目的,即代码方式:

我的数据类似于以下内容。

  ID  | DEAD     | 2009-10 | ...    | 2016-10
 -----------------------------------------
  1   | 2018-11  | 5.4     | ...    | 6.5 
  2   | 2014-01  | 0.5     | ...    | 5.2
  ...                      
  N   | 2008-11  | 8.6     | ...    | 1.3

目标是在产品到期后(“ DEAD”列<日期)时立即用np.NaN替换值,否则值应保持不变。

  ID  | DEAD     | 2009-10 | ...    | 2016-10
 -----------------------------------------
  1   | 2018-11  | 5.4     | ...    | 6.5 
  2   | 2014-01  | 0.5     | ...    | NaN
  ...                      
  N   | 2008-11  | 8.6     | ...    | NaN

我的最初想法是应用嵌套的for循环来检查是否达到条件'DEAD' < date。该方法适用于较小的N。但是由于我的数据包括20,000行和400列,因此需要太多时间。

time = df.columns[2:] # take the header as an index
time = pd.DataFrame(time)
time.columns = ['Dummy']
time['Dummy'] = pd.to_datetime(time.Dummy) # Convert index argument to datetime

df['DEAD'] = pd.to_datetime(tore.DEAD) # Convert column 'DEAD' to datetime



lists = []
for i in range(397):
    row = []
    for j in range(20000):
        if time.iloc[i,0] <= df.iloc[j,0]: 
            newlist = df.iloc[j,i]
        else:
            newlist = np.NaN
        row.append(newlist)
    lists.append(row)

lists = pd.DataFrame(lists)
lists = lists.transpose()

感谢任何建议!

3 个答案:

答案 0 :(得分:4)

您可以尝试遍历每列:

for column_name in df.drop('DEAD', axis=1):
   column_date = pd.to_datetime(column_name)
   df[column_name].mask(df['DEAD']<column_date, inplace=True)

此处的mask方法也很有用。

答案 1 :(得分:1)

如果列是有序的(例如,按日期升序),则可以避免某些循环和检查。

  • 对于每一行,找到满足您条件的第一列
    • 如果您确实想进行优化,则可以通过二分搜索来做到这一点
  • 获取此列的索引;称为i
  • 使用index >= i将所有后续列更新为NaN

更新本身仍在逐个单元完成,可能效果不佳。

如果创建第二个数据框,其尺寸可以像位掩码一样使用,并且包含指示是否应保留基础数据框中的值的01值,则可能会获得更好的性能或删除。

答案 2 :(得分:0)

如果此数据存储在数据库中,则应直接使用sql进行操作,速度要快得多。