【问题标题】:pandas dataframe create a new dataframe by duplicating n times rows of the previous dataframe and change date熊猫数据框通过复制前一个数据框的n次行并更改日期来创建一个新的数据框
【发布时间】:2018-03-04 23:57:19
【问题描述】:

我有一个大约 9k 行和 57 列的数据框,这是“df”。

我需要一个新的数据框:'df_final' - 对于“df”的每一行,我必须将每一行复制“x”次,并将每一行中的日期一一增加,也是“x”次。 虽然我可以进行几次迭代,但当我为 'df' ' len(df)' 的全长执行此操作时,循环需要很长时间(> 3 小时),以至于我实际上不得不取消它。我从未见过它的结局。这是当前代码:

df.shape
output: (9454, 57)

df_int = df[0:0]
df_final = df_int[0:0]
range_df = len(df)
for x in range(0,2):
    df_int = df.iloc[0+x:x+1]
    if abs(df_int.iat[-1,3]) > 0:
        df_int = pd.concat([df_int]*abs(df_int.iat[-1,3]), ignore_index=True)
        for i in range(1, abs(df_int.iat[-1,3])):
            df_int['Consumption Date'][i] = df_int['Consumption Date'][i-1] + datetime.timedelta(days = 1)
            i += 1
       df_final = df_final.append(df_int, ignore_index=True)
    x += 1

“df”前两行的循环结果如下。

df 的前两行:

期望的结果:

是否有另一种方法可以获得所需的输出。熊猫似乎不能很好地处理循环。在 VBA excel 中,相同的循环大约需要 3/4 分钟......我正在尝试将当前在 excel 中的进程更改为 python,但是,如果没有办法完成这项工作,我想我会坚持旧方法。 ..

【问题讨论】:

    标签: python pandas loops dataframe rows


    【解决方案1】:

    使用repeatcumcount

    In [2972]: dff = df.loc[df.index.repeat(3)]
    
    In [2973]: dff
    Out[2973]:
            date   name
    0 2017-05-03    bob
    0 2017-05-03    bob
    0 2017-05-03    bob
    1 2017-06-13  sally
    1 2017-06-13  sally
    1 2017-06-13  sally
    
    In [2974]: dff.loc[:, 'date'] += pd.to_timedelta(dff.groupby(level=0).cumcount(), 'D')
    
    In [2975]: dff
    Out[2975]:
            date   name
    0 2017-05-03    bob
    0 2017-05-04    bob
    0 2017-05-05    bob
    1 2017-06-13  sally
    1 2017-06-14  sally
    1 2017-06-15  sally
    

    详情

    In [2976]: df
    Out[2976]:
            date   name
    0 2017-05-03    bob
    1 2017-06-13  sally
    
    In [2977]: dff.groupby(level=0).cumcount()
    Out[2977]:
    0    0
    0    1
    0    2
    1    0
    1    1
    1    2
    dtype: int64
    

    【讨论】:

    • 非常好的溶胶
    【解决方案2】:

    让我们使用这个玩具 DataFrame:

    df = pd.DataFrame({
        'date': pd.to_datetime(['2017-05-03', '2017-06-13']),
        'name': ['bob', 'sally'],
    })
    

    看起来像这样:

            date   name
    0 2017-05-03    bob
    1 2017-06-13  sally
    

    然后:

    x = 3 # repeat count
    ind = np.repeat(np.arange(len(df)), x) # 0,0,0,1,1,1
    df_final = df.iloc[ind].copy()
    

    这给了你重复:

            date   name
    0 2017-05-03    bob
    0 2017-05-03    bob
    0 2017-05-03    bob
    1 2017-06-13  sally
    1 2017-06-13  sally
    1 2017-06-13  sally
    

    现在你只需要增加日期:

    inc = np.tile(np.arange(x), len(df)) # 0,1,2,0,1,2
    df_final.date += pd.to_timedelta(inc, 'D')
    

    你会得到:

            date   name
    0 2017-05-03    bob
    0 2017-05-04    bob
    0 2017-05-05    bob
    1 2017-06-13  sally
    1 2017-06-14  sally
    1 2017-06-15  sally
    

    【讨论】:

      【解决方案3】:

      这是一种解决方案

      df1=df.reset_index().set_index('date').groupby('index').\
          apply(lambda x :x.reindex(pd.date_range(start=x.index[0],periods=3,freq='D'))).ffill()
      df1
      Out[202]: 
                        index   name
      index                         
      0     2017-05-03    0.0    bob
            2017-05-04    0.0    bob
            2017-05-05    0.0    bob
      1     2017-06-13    1.0  sally
            2017-06-14    1.0  sally
            2017-06-15    1.0  sally
      

      然后

      df1.drop('index',1).reset_index().rename(columns={'level_1':'date'}).drop('index',1)
      
      Out[212]: 
              date   name
      0 2017-05-03    bob
      1 2017-05-04    bob
      2 2017-05-05    bob
      3 2017-06-13  sally
      4 2017-06-14  sally
      5 2017-06-15  sally
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多