Python 如何用更快的方法替换FOR循环

Python 如何用更快的方法替换FOR循环,python,numpy,for-loop,vectorization,list-comprehension,Python,Numpy,For Loop,Vectorization,List Comprehension,我正试图根据某些条件转换我的数据帧。下面是我的输入数据帧 In [11]: df Out[11]: DocumentNumber I_Date N_Date P_Date Amount 0 1234 2016-01-01 2017-01-01 2017-10-23 38.38 1 2345 2016-01-02 2017-01-02 2018-03-26 41.00 2 1324 2016

我正试图根据某些条件转换我的数据帧。下面是我的输入数据帧

In [11]: df
Out[11]: 
   DocumentNumber     I_Date     N_Date     P_Date  Amount
0            1234 2016-01-01 2017-01-01 2017-10-23   38.38
1            2345 2016-01-02 2017-01-02 2018-03-26   41.00
2            1324 2016-01-12 2017-01-03 2018-03-26   30.37
3            5421 2016-01-13 2017-01-02 2018-03-06  269.00
4            5532 2016-01-15 2017-01-04 2018-06-30  271.00
理想的解决方案:
  • 每一行都是一个独特的文档,我的目标是找到文档的数量和它们的总数,如果我每天运行一次,那么这些文档的数量和总数满足上述条件
  • 我可以通过
    for loop
    获得所需的结果,但我知道这不是理想的方法,而且随着数据的增加,速度会变慢。由于我是python新手,我需要通过列表理解或任何其他更快的选项来帮助摆脱循环
代码:
  • 我看不到从代码中删除循环的方法,因为循环基于
    mydates
    Delta
    的内容创建单个数据帧。
    • 在本例中,您将创建75个不同的数据帧
    • 在每个数据帧上,您可以
      .groupby
      ,然后
      .agg
      支付的
      总额
      和文档编号的
      计数
    • 每个数据帧都附加到一个列表中
    • pd.concat
      将完整列表放入数据框中
  • 一项重大改进
    • 在创建数据帧并执行其余操作之前,请检查布尔条件。在本例中,对69个空数据帧执行了操作。通过首先检查条件,将仅对包含数据的6个数据帧执行操作
    • condition.any()
      返回
      True
      ,只要至少有一个元素
      True
  • 小变化
    • datetime
      +
      int
      已被弃用,因此将其更改为
      datetime
      +
      timedelta(days=x)
    • pd.Series(范围(0,5)).tolist()
      对于制作列表来说是一种过分的技巧。现在需要
      timedelta
      对象,因此使用
      [timedelta(days=x)表示范围(5)中的x]
    • 使用
      mydates
      Delta
      上的
      itertools.product
      ,而不是对循环使用两个
      进行迭代。这将创建一个元组生成器,格式为
      (Timestamp('2017-01-01 00:00:00',freq='D')、datetime.timedelta(0))
    • 创建数据帧
      A
      时使用
      .copy()
      ,以防止
      设置CopyWarning
  • 注:
    • 问题中提到了
      列表理解
      。它们只是一种
      pythonic
      的方法,用于生成
      for循环
      ,但不一定能提高性能
    • 所有的计算都使用pandas方法,而不是循环的
      。循环的
      仅根据条件创建数据帧
  • 更新代码: 来自itertools导入产品的
    
    作为pd进口熊猫
    从日期时间导入日期,时间增量
    d1=日期(2017年1月1日)
    d2=日期(2017年1月15日)
    mydates=pd.date\u范围(d1、d2)
    增量=[范围(5)内x的时间增量(天数=x)]
    df_list=list()
    对于产品中的t(mydates,Delta):
    条件=(df[“I_日期”]t[0]+t[1])和(df[“P_日期”]>t[0])
    if条件.any():
    A=df[条件].copy()
    A[“日期截止”]=t[0]
    A[“Delta”]=t[1]
    A=A.groupby(['DateCutoff','Delta'],as_index=False).agg({'Amount':'sum','DocumentNumber':'count'})
    A.columns=['DateCutoff'、'Delta'、'A_PaymentAmount'、'A_DocumentNumber']
    df_列表。附加(A)
    df_截止=pd.concat(df_列表,排序=False)
    
    输出
    • 和原来一样
    DateCutoff Delta A_PaymentAmount A_DocumentNumber
    0 2017-01-01      0           611.37                 4
    0 2017-01-01      1           301.37                 2
    0 2017-01-01      2           271.00                 1
    0 2017-01-02      0           301.37                 2
    0 2017-01-02      1           271.00                 1
    0 2017-01-03      0           271.00                 1
    
  • 我看不到从代码中删除循环的方法,因为循环基于
    mydates
    Delta
    的内容创建单个数据帧。
    • 在本例中,您将创建75个不同的数据帧
    • 在每个数据帧上,您可以
      .groupby
      ,然后
      .agg
      支付的
      总额
      和文档编号的
      计数
    • 每个数据帧都附加到一个列表中
    • pd.concat
      将完整列表放入数据框中
  • 一项重大改进
    • 在创建数据帧并执行其余操作之前,请检查布尔条件。在本例中,对69个空数据帧执行了操作。通过首先检查条件,将仅对包含数据的6个数据帧执行操作
    • condition.any()
      返回
      True
      ,只要至少有一个元素
      True
  • 小变化
    • datetime
      +
      int
      已被弃用,因此将其更改为
      datetime
      +
      timedelta(days=x)
    • pd.Series(范围(0,5)).tolist()
      对于制作列表来说是一种过分的技巧。现在需要
      timedelta
      对象,因此使用
      [timedelta(days=x)表示范围(5)中的x]
    • 使用
      mydates
      Delta
      上的
      itertools.product
      ,而不是对循环使用两个
      进行迭代。这将创建一个元组生成器,格式为
      (Timestamp('2017-01-01 00:00:00',freq='D')、datetime.timedelta(0))
    • 创建数据帧
      A
      时使用
      .copy()
      ,以防止
      设置CopyWarning
  • 注:
    • 问题中提到了
      列表理解
      。它们只是一种
      pythonic
      的方法,用于生成
      for循环
      ,但不一定能提高性能
    • 所有的计算都使用pandas方法,而不是循环的
      <
      
      d1 = datetime.date(2017, 1, 1)
      d2 = datetime.date(2017, 1, 15)
      
      mydates = pd.date_range(d1, d2).tolist()
      Delta = pd.Series(range(0,5)).tolist()
      
      df_A =[]
      
      
      for i in mydates: 
          for j in Delta:
              A = df[(df["I_Date"]<i) & (df["N_Date"]>i+j) & (df["P_Date"]>i) ]
              A["DateCutoff"] = i
              A["Delta"]=j
              A = A.groupby(['DateCutoff','Delta'],as_index=False).agg({'Amount':'sum','DocumentNumber':'count'})
              A.columns = ['DateCutoff','Delta','A_PaymentAmount','A_DocumentNumber']
              df_A.append(A)
      
      df_A = pd.concat(df_A, sort = False)
      
      In [14]: df_A
      Out[14]: 
        DateCutoff  Delta  A_PaymentAmount  A_DocumentNumber
      0 2017-01-01      0           611.37                 4
      0 2017-01-01      1           301.37                 2
      0 2017-01-01      2           271.00                 1
      0 2017-01-02      0           301.37                 2
      0 2017-01-02      1           271.00                 1
      0 2017-01-03      0           271.00                 1