【问题标题】:How to perform time series analysis that contains multiple groups in Python using fbProphet or other models?如何使用 fbProphet 或其他模型在 Python 中执行包含多个组的时间序列分析?
【发布时间】:2019-08-27 22:54:23
【问题描述】:

全部,

我的数据集如下所示。我正在尝试使用fbProphet 或其他模型来预测未来 6 个月的“金额”。但我的问题是,我想根据每个组(即 A、B、C、D)预测未来 6 个月的金额。我不确定如何在python 中使用fbProphet 或其他模型来做到这一点?我引用了official page of fbprophet,但我发现的唯一信息是“Prophet”只有两列,一个是“Date”,另一个是“amount”。

我是 python 新手,非常感谢任何关于代码解释的帮助!

import pandas as pd
data = {'Date':['2017-01-01', '2017-02-01', '2017-03-01', '2017-04-01','2017-05-01','2017-06-01','2017-07-01'],'Group':['A','B','C','D','C','A','B'],
       'Amount':['12.1','13','15','10','12','9.0','5.6']}
df = pd.DataFrame(data)
print (df)

输出:

         Date Group Amount
0  2017-01-01     A   12.1
1  2017-02-01     B     13
2  2017-03-01     C     15
3  2017-04-01     D     10
4  2017-05-01     C     12
5  2017-06-01     A    9.0
6  2017-07-01     B    5.6

【问题讨论】:

  • 组是独立的吗?或者一组的金额是否取决于另一组?
  • 组相互独立。

标签: python pandas time-series facebook-prophet


【解决方案1】:

我知道这是旧的,但我试图预测不同客户的结果,我尝试使用上面的 Aditya Santoso 解决方案但遇到了一些错误,所以我添加了一些修改,最后这对我有用:

df = pd.read_csv('file.csv')
df = pd.DataFrame(df)
df = df.rename(columns={'date': 'ds', 'amount': 'y', 'client_id': 'client_id'})
#I had to filter first clients with less than 3 records to avoid errors as prophet only works for 2+ records by group
df = df.groupby('client_id').filter(lambda x: len(x) > 2)

df.client_id = df.client_id.astype(str)

final = pd.DataFrame(columns=['client','ds','yhat'])

grouped = df.groupby('client_id')
for g in grouped.groups:
    group = grouped.get_group(g)
    m = Prophet()
    m.fit(group)
    future = m.make_future_dataframe(periods=365)
    forecast = m.predict(future)
    #I added a column with client id
    forecast['client'] = g
    #I used concat instead of merge
    final = pd.concat([final, forecast], ignore_index=True)

final.head(10)

【讨论】:

    【解决方案2】:
    import pandas as pd
    import numpy as np
    from statsmodels.tsa.statespace.sarimax import SARIMAX
    from statsmodels.tsa.arima_model import ARIMA
    from statsmodels.tsa.stattools import adfuller
    from matplotlib import pyplot as plt
    from sklearn.metrics import mean_squared_error
    from sklearn.metrics import mean_squared_log_error  
    
    
    
    # Before doing any modeling using ARIMA or SARIMAS etc Confirm that
    # your time-series is stationary by using Augmented Dick Fuller test
    # or other tests.
    
    # Create a list of all groups or get from Data using np.unique or other methods
    groups_iter = ['A', 'B', 'C', 'D']
    
    dict_org = {}
    dict_pred = {}
    group_accuracy = {}
    
    # Iterate over all groups and get data 
    # from Dataframe by filtering for specific group
    for i in range(len(groups_iter)):
        X = data[data['Group'] == groups_iter[i]]['Amount'].values
        size = int(len(X) * 0.70)
        train, test = X[0:size], X[size:len(X)]
        history = [x for in train]
    
        # Using ARIMA model here you can also do grid search for best parameters
        for t in range(len(test)):
            model = ARIMA(history, order = (5, 1, 0))
            model_fit = model.fit(disp = 0)
            output = model_fit.forecast()
            yhat = output[0]
            predictions.append(yhat)
            obs = test[t]
            history.append(obs)
            print("Predicted:%f, expected:%f" %(yhat, obs))
        error = mean_squared_log_error(test, predictions)
        dict_org.update({groups_iter[i]: test})
        dict_pred.update({group_iter[i]: test})
    
        print("Group: ", group_iter[i], "Test MSE:%f"% error)
        group_accuracy.update({group_iter[i]: error})
        plt.plot(test)
        plt.plot(predictions, color = 'red')
        plt.show()
    

    【讨论】:

    • 此外,您还可以查看不同组的多变量聚类,因为每个组可能具有不同的季节性和趋势。显示相似模式的组将被分组到一个集群中,您可以对它们应用相同的算法。
    • 集群的好主意!如果您在同一日期有多个单独的组,您会如何建议使用额外的训练数据?例如。预测两种 T 恤的销量,我们现在在时间序列中的每个日期都有 2 个销售数据,并且两者应该表现出相似的模式
    • 我认为这个问题回答了你的问题。 stats.stackexchange.com/questions/289163/…
    【解决方案3】:

    fbprophet需要dsy两列,所以需要先重命名这两列

    df = df.rename(columns={'Date': 'ds', 'Amount':'y'})
    

    假设您的组彼此独立并且您希望为每个组获得一个预测,您可以按“组”列对数据框进行分组并为每个组运行预测

    from fbprophet import Prophet
    grouped = df.groupby('Group')
    for g in grouped.groups:
        group = grouped.get_group(g)
        m = Prophet()
        m.fit(group)
        future = m.make_future_dataframe(periods=365)
        forecast = m.predict(future)
        print(forecast.tail())
    

    请注意,您在问题中提供的输入数据框对于模型来说是不够的,因为 D 组只有一个数据点。 fbprophet 的预测至少需要 2 个非 Nan 行。

    编辑:如果您想将所有预测合并到一个数据帧中,想法是为每个观察值分别命名 yhat,在循环中执行 pd.merge(),然后在结束:

    final = pd.DataFrame()
    for g in grouped.groups:
        group = grouped.get_group(g)
        m = Prophet()
        m.fit(group)
        future = m.make_future_dataframe(periods=365)
        forecast = m.predict(future)    
        forecast = forecast.rename(columns={'yhat': 'yhat_'+g})
        final = pd.merge(final, forecast.set_index('ds'), how='outer', left_index=True, right_index=True)
    
    final = final[['yhat_' + g for g in grouped.groups.keys()]]
    

    【讨论】:

    • 谢谢!您是否也可以展示另一种方法?也许没有使用 fbProphet。我在发布这个问题后意识到由于某种原因 fbProphet 无法安装在我的系统上。我也尝试过 pip install .. 提前致谢!
    • 另外,我怎么知道哪个预测是针对哪个组的?我想存储我组的预测,以便 0、1、2、3 列中的数据代表 A、B、C、D 组的预测?
    • 上面的代码已经对每个组进行了预测。如果您想合并到一个包含所有组的 yhat 数据的巨大数据帧中,您可以在循环中对每个组执行 pd.merge()
    • 。感谢代码和解释!上面的代码适用于小数据集。但是,我的数据集包含约 7 组的 83,000 行。当我尝试在建议的代码之上运行时。我收到 MemoryError 问题。我检查了我的 python 位,它是 64 位的。有没有办法,我可以把代码分成两个组件?我很好奇我是否可以创建我的数据框并稍后附加它。我试过了,但不幸的是收到了索引错误。据我了解,预测变量仅显示/保存最后分组的数据。我认为这是错误的原因。有关如何解决此问题的任何建议?
    • @Data_is_Power:在合并或预测时会遇到 MemoryError 吗?它究竟消耗了多少内存?一个建议是隔离问题是将每个组的预测转储到 pickle 或 csv,而不是合并到一个巨大的数据帧中。然后创建另一个进程只是为了进行最终合并。如果您在合并/附加数据框时遇到问题,也许您应该为此打开一个单独的问题。
    猜你喜欢
    • 1970-01-01
    • 2016-11-29
    • 2019-10-16
    • 1970-01-01
    • 1970-01-01
    • 2015-12-31
    • 2017-05-12
    • 1970-01-01
    相关资源
    最近更新 更多