【问题标题】:Python Pandas: Inserting new rows for date gaps in dataPython Pandas:为数据中的日期间隔插入新行
【发布时间】:2015-04-18 07:10:42
【问题描述】:

我有这样的 Pandas 数据框

Date      Curr    Amount
1/1/2015  USD 100.00
1/2/2015  USD 125.00
1/5/2015  USD 110.00
1/6/2015  USD 115.00

1/1/2015  AUD 100.00
1/2/2015  AUD 125.00
1/5/2015  AUD  110.00
1/6/2015  AUD 115.00

想要的输出

    Date  curr  Amount
1/1/2015  usd 100.00
1/2/2015  usd 125.00
1/3/2015  usd 125.00
1/4/2015  usd 125.00
1/5/2015  usd 110.00
1/6/2015  usd 115.00
1/1/2015  aud 100.00
1/2/2015  aud 125.00
1/3/2015  aud 125.00
1/4/2015  aud 125.00
1/5/2015  aud 110.00
1/6/2015  aud 115.00

源数据只记录金额的变化,我想插入缺失的日期,金额预先跳过。

在我的示例中,它从 1/2 跳到 1/5。我希望金额列使用 1/2 金额填写并为缺少的日期创建 3 个新行。

谢谢

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    一条很长的两条线,应该分开:

    idx = pd.DatetimeIndex(start=min(df.Date), end=max(df.Date), freq='D')
    df2 = (pd.DataFrame(df.set_index(['Date', 'Curr']).unstack('Curr'), index=idx).fillna(0) 
    + df.set_index(['Date', 'Curr']).unstack('Curr')).ffill().stack()
    >>> df2
                     Amount
               Curr        
    2015-01-01 AUD      100
               USD      100
    2015-01-02 AUD      125
               USD      125
    2015-01-03 AUD      125
               USD      125
    2015-01-04 AUD      125
               USD      125
    2015-01-05 AUD      110
               USD      110
    2015-01-06 AUD      115
               USD      115
    

    详细来看,我首先使用原始 DataFrame 中的最小和最大日期创建一个 DatetimeIndex。我将频率设置为每日 ('D'),但您可能希望使用另一个 offset frequency,例如工作日 ('B'):

    idx = pd.DatetimeIndex(start=min(df.Date), end=max(df.Date), freq='D')
    

    然后我解开 DataFrame 的堆栈,这样我就只有索引中的日期了。

    df_temp = df.set_index(['Date', 'Curr']).unstack('Curr')
    
    >>> df_temp
              Amount     
    Curr         AUD  USD
    Date                 
    1/1/2015     100  100
    1/2/2015     125  125
    1/5/2015     110  110
    1/6/2015     115  115
    

    我创建了一个临时 DataFrame,它将全部是 NaN,但包含我新的扩展日期列表。我用零填充这个 DataFrame 并用 df_temp 中的值覆盖它:

    df_temp2 = (pd.DataFrame(df_temp, index=idx).fillna(0) + df_temp)
    
    >>> df_temp2
                Amount     
    Curr           AUD  USD
    2015-01-01     100  100
    2015-01-02     125  125
    2015-01-03     NaN  NaN
    2015-01-04     NaN  NaN
    2015-01-05     110  110
    2015-01-06     115  115
    

    最后,我填写值以删除 NaN,并堆叠货币:

    >>> df_temp2.ffill().stack() 
                     Amount
               Curr        
    2015-01-01 AUD      100
               USD      100
    2015-01-02 AUD      125
               USD      125
    2015-01-03 AUD      125
               USD      125
    2015-01-04 AUD      125
               USD      125
    2015-01-05 AUD      110
               USD      110
    2015-01-06 AUD      115
               USD      115
    

    【讨论】:

      【解决方案2】:

      你很想做和这里一样的事情: How to fill the missing record of Pandas dataframe in pythonic way?

      您需要构建一个完整的索引,然后使用带有前向填充'ffill' 选项的fillna 方法。

      import pandas
      from io import StringIO
      data = StringIO("""\
      Date      Curr    Amount
      1/1/2015  USD 100.00
      1/2/2015  USD 125.00
      1/5/2015  USD 110.00
      1/6/2015  USD 115.00
      1/1/2015  AUD 100.00
      1/2/2015  AUD 125.00
      1/5/2015  AUD 110.00
      1/6/2015  AUD 115.00
      """)
      
      df = pandas.read_table(data, sep='\s+', parse_dates=[0])
      
      full_index = pandas.MultiIndex.from_product([
              pandas.date_range(start='2015-01-01', end='2015-01-08'),
              ['USD', 'AUD']        
      ], names=['Date', 'Curr'])
      df2 = (
          df.set_index(['Date', 'Curr'])
            .reindex(full_index)
            .unstack(level='Curr') # pivot Curr into columns
            .fillna(method='ffill')  # drag the last valid value into the NaNs
            .stack(level='Curr')  # put Curr back into rows
            .reset_index()  # remove the index
            .sort(['Curr', 'Date']) # sort the row
            .reset_index(drop=True) # set the index back to 0, 1, ... N
      )
      print(df2)
      

      这给了我们:

               Date Curr  Amount
      0  2015-01-01  AUD     100
      1  2015-01-02  AUD     125
      2  2015-01-03  AUD     125
      3  2015-01-04  AUD     125
      4  2015-01-05  AUD     110
      5  2015-01-06  AUD     115
      6  2015-01-07  AUD     115
      7  2015-01-08  AUD     115
      8  2015-01-01  USD     100
      9  2015-01-02  USD     125
      10 2015-01-03  USD     125
      11 2015-01-04  USD     125
      12 2015-01-05  USD     110
      13 2015-01-06  USD     115
      14 2015-01-07  USD     115
      15 2015-01-08  USD     115
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-22
        • 1970-01-01
        • 1970-01-01
        • 2018-02-02
        • 2016-05-05
        • 1970-01-01
        • 2020-08-25
        • 1970-01-01
        相关资源
        最近更新 更多