简体   繁体   中英

How to extrapolate missing values with groupby - Python?

I have the following dataset:

data = {
  'date': ['1/1/2019', '1/2/2019', '1/3/2019', '1/4/2019', '1/1/2019', '1/2/2019', '1/3/2019', '1/4/2019'],
  'account_id': [1, 1, 1, 1, 2, 2, 2, 2],
  'value_1': [1, 2, 3, 4, 5, 6, 7, 8],
  'value_2': [1, 3, 6, 9, 10, 12, 14, 16]
}
df = pd.DataFrame(data,index = data['date']).drop('date', 1)
df

What I need is to extrapolate value 1 and value 2 forward by 30 days.

I came across Extrapolate Pandas DataFrame . It would work beautifully if there were no duplicated entries in the date column.

I thought of using sth of this sort but I don't understand how to add v to the function:

def extrapolation(df):
    extend = 1
    y = pd.DataFrame(
        data=df,
        index=pd.date_range(
            start=df.index[0],
            periods=len(df.index) + extend
        )
    )
    #then, the extrapolation piece


df_out=df.head(0).copy()
for k,v in df.groupby('account_id'):
    df_out=pd.concat([df_out,extrapolation(df)])

You can modify the linked answer as follows:

def extrapolate(df):
    new_max = df.index.max() + pd.to_timedelta('30D')
    dates = pd.date_range(df.index.min(), new_max, freq='D')
    ret_df = df.reindex(dates)

    x = np.arange(len(df))

    # new x values
    new_x = pd.Series(np.arange(len(ret_df)), index=dates)

    for col in df.columns:
        fit = np.polyfit(x, df[col], 1)

        # tranform and fill
        ret_df[col].fillna(fit[0]*new_x + fit[1], inplace=True)

    return ret_df

and then apply:

ext_cols = ['value_1', 'value_2']

df.groupby('account_id')[ext_cols].apply(extrapolate)

You can also specify the polynomial orders for each column:

poly_orders = [1,2]
ext_cols = ['value_1', 'value_2']

def extrapolate(df):
    new_max = df.index.max() + pd.to_timedelta('30D')
    dates = pd.date_range(df.index.min(), new_max, freq='D')
    ret_df = df.reindex(dates)

    x = np.arange(len(df))

    # new x values
    new_x = pd.Series(np.arange(len(ret_df)), index=dates)

    for col, o in zip(ext_cols, poly_orders):
        fit = np.polyfit(x, df[col], o)

        print(fit)

        # tranform and fill
        new_vals = pd.Series(0, index=dates)

        for i in range(1,o+1):
            new_vals = new_x**i * fit[o-i]

        ret_df[col].fillna(new_vals, inplace=True)

    return ret_df

And use sklearn.linear_model.LinearRegression for better manipulation of input/output instead of numpy.polyfit .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM