We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Issue in removing nan's from the trend variable
Hi,
I am trying to use your code given in the link: https://github.com/statsmodels/statsmodels/blob/master/statsmodels/tsa/seasonal.py
to remove the nan's which occur due to the moving averages. When i put the variable extrapolate_trend >0 then i get a value error saying: 
ValueError: could not broadcast input array from shape (26,1) into shape (26)
I want to extrapolate the trend values for a time series at a week level

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `statsmodels/tsa/seasonal.py`
Content:
```
1 """
2 Seasonal Decomposition by Moving Averages
3 """
4 from statsmodels.compat.python import lmap, range, iteritems
5 import numpy as np
6 from pandas.core.nanops import nanmean as pd_nanmean
7 from .filters._utils import (_maybe_get_pandas_wrapper_freq,
8                              _maybe_get_pandas_wrapper)
9 from .filters.filtertools import convolution_filter
10 from statsmodels.tsa.tsatools import freq_to_period
11 
12 
13 def seasonal_mean(x, freq):
14     """
15     Return means for each period in x. freq is an int that gives the
16     number of periods per cycle. E.g., 12 for monthly. NaNs are ignored
17     in the mean.
18     """
19     return np.array([pd_nanmean(x[i::freq], axis=0) for i in range(freq)])
20 
21 
22 def _extrapolate_trend(trend, npoints):
23     """
24     Replace nan values on trend's end-points with least-squares extrapolated
25     values with regression considering npoints closest defined points.
26     """
27     front = next(i for i, vals in enumerate(trend)
28                  if not np.any(np.isnan(vals)))
29     back = trend.shape[0] - 1 - next(i for i, vals in enumerate(trend[::-1])
30                                      if not np.any(np.isnan(vals)))
31     front_last = min(front + npoints, back)
32     back_first = max(front, back - npoints)
33 
34     k, n = np.linalg.lstsq(
35         np.c_[np.arange(front, front_last), np.ones(front_last - front)],
36         trend[front:front_last])[0]
37     trend[:front] = (np.arange(0, front) * np.c_[k] + np.c_[n]).T
38 
39     k, n = np.linalg.lstsq(
40         np.c_[np.arange(back_first, back), np.ones(back - back_first)],
41         trend[back_first:back])[0]
42     trend[back + 1:] = (np.arange(back + 1, trend.shape[0]) * np.c_[k] + np.c_[n]).T
43 
44     return trend
45 
46 
47 def seasonal_decompose(x, model="additive", filt=None, freq=None, two_sided=True,
48                        extrapolate_trend=0):
49     """
50     Seasonal decomposition using moving averages
51 
52     Parameters
53     ----------
54     x : array-like
55         Time series. If 2d, individual series are in columns.
56     model : str {"additive", "multiplicative"}
57         Type of seasonal component. Abbreviations are accepted.
58     filt : array-like
59         The filter coefficients for filtering out the seasonal component.
60         The concrete moving average method used in filtering is determined by two_sided.
61     freq : int, optional
62         Frequency of the series. Must be used if x is not a pandas object.
63         Overrides default periodicity of x if x is a pandas
64         object with a timeseries index.
65     two_sided : bool
66         The moving average method used in filtering.
67         If True (default), a centered moving average is computed using the filt.
68         If False, the filter coefficients are for past values only.
69     extrapolate_trend : int or 'freq', optional
70         If set to > 0, the trend resulting from the convolution is
71         linear least-squares extrapolated on both ends (or the single one
72         if two_sided is False) considering this many (+1) closest points.
73         If set to 'freq', use `freq` closest points. Setting this parameter
74         results in no NaN values in trend or resid components.
75 
76     Returns
77     -------
78     results : obj
79         A object with seasonal, trend, and resid attributes.
80 
81     Notes
82     -----
83     This is a naive decomposition. More sophisticated methods should
84     be preferred.
85 
86     The additive model is Y[t] = T[t] + S[t] + e[t]
87 
88     The multiplicative model is Y[t] = T[t] * S[t] * e[t]
89 
90     The seasonal component is first removed by applying a convolution
91     filter to the data. The average of this smoothed series for each
92     period is the returned seasonal component.
93 
94     See Also
95     --------
96     statsmodels.tsa.filters.bk_filter.bkfilter
97     statsmodels.tsa.filters.cf_filter.xffilter
98     statsmodels.tsa.filters.hp_filter.hpfilter
99     statsmodels.tsa.filters.convolution_filter
100     """
101     if freq is None:
102         _pandas_wrapper, pfreq = _maybe_get_pandas_wrapper_freq(x)
103     else:
104         _pandas_wrapper = _maybe_get_pandas_wrapper(x)
105         pfreq = None
106     x = np.asanyarray(x).squeeze()
107     nobs = len(x)
108 
109     if not np.all(np.isfinite(x)):
110         raise ValueError("This function does not handle missing values")
111     if model.startswith('m'):
112         if np.any(x <= 0):
113             raise ValueError("Multiplicative seasonality is not appropriate "
114                              "for zero and negative values")
115 
116     if freq is None:
117         if pfreq is not None:
118             pfreq = freq_to_period(pfreq)
119             freq = pfreq
120         else:
121             raise ValueError("You must specify a freq or x must be a "
122                              "pandas object with a timeseries index with "
123                              "a freq not set to None")
124 
125     if filt is None:
126         if freq % 2 == 0:  # split weights at ends
127             filt = np.array([.5] + [1] * (freq - 1) + [.5]) / freq
128         else:
129             filt = np.repeat(1./freq, freq)
130 
131     nsides = int(two_sided) + 1
132     trend = convolution_filter(x, filt, nsides)
133 
134     if extrapolate_trend == 'freq':
135         extrapolate_trend = freq - 1
136 
137     if extrapolate_trend > 0:
138         trend = _extrapolate_trend(trend, extrapolate_trend + 1)
139 
140     if model.startswith('m'):
141         detrended = x / trend
142     else:
143         detrended = x - trend
144 
145     period_averages = seasonal_mean(detrended, freq)
146 
147     if model.startswith('m'):
148         period_averages /= np.mean(period_averages, axis=0)
149     else:
150         period_averages -= np.mean(period_averages, axis=0)
151 
152     seasonal = np.tile(period_averages.T, nobs // freq + 1).T[:nobs]
153 
154     if model.startswith('m'):
155         resid = x / seasonal / trend
156     else:
157         resid = detrended - seasonal
158 
159     results = lmap(_pandas_wrapper, [seasonal, trend, resid, x])
160     return DecomposeResult(seasonal=results[0], trend=results[1],
161                            resid=results[2], observed=results[3])
162 
163 
164 class DecomposeResult(object):
165     def __init__(self, **kwargs):
166         for key, value in iteritems(kwargs):
167             setattr(self, key, value)
168         self.nobs = len(self.observed)
169 
170     def plot(self):
171         from statsmodels.graphics.utils import _import_mpl
172         plt = _import_mpl()
173         fig, axes = plt.subplots(4, 1, sharex=True)
174         if hasattr(self.observed, 'plot'):  # got pandas use it
175             self.observed.plot(ax=axes[0], legend=False)
176             axes[0].set_ylabel('Observed')
177             self.trend.plot(ax=axes[1], legend=False)
178             axes[1].set_ylabel('Trend')
179             self.seasonal.plot(ax=axes[2], legend=False)
180             axes[2].set_ylabel('Seasonal')
181             self.resid.plot(ax=axes[3], legend=False)
182             axes[3].set_ylabel('Residual')
183         else:
184             axes[0].plot(self.observed)
185             axes[0].set_ylabel('Observed')
186             axes[1].plot(self.trend)
187             axes[1].set_ylabel('Trend')
188             axes[2].plot(self.seasonal)
189             axes[2].set_ylabel('Seasonal')
190             axes[3].plot(self.resid)
191             axes[3].set_ylabel('Residual')
192             axes[3].set_xlabel('Time')
193             axes[3].set_xlim(0, self.nobs)
194 
195         fig.tight_layout()
196         return fig
197 
198 
199 if __name__ == "__main__":
200     x = np.array([-50, 175, 149, 214, 247, 237, 225, 329, 729, 809,
201                   530, 489, 540, 457, 195, 176, 337, 239, 128, 102,
202                   232, 429, 3, 98, 43, -141, -77, -13, 125, 361, -45, 184])
203     results = seasonal_decompose(x, freq=4)
204 
205     from pandas import DataFrame, DatetimeIndex
206     data = DataFrame(x, DatetimeIndex(start='1/1/1951',
207                                       periods=len(x),
208                                       freq='Q'))
209 
210     res = seasonal_decompose(data)
211 
212
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/statsmodels/tsa/seasonal.py b/statsmodels/tsa/seasonal.py
--- a/statsmodels/tsa/seasonal.py
+++ b/statsmodels/tsa/seasonal.py
@@ -34,12 +34,18 @@
     k, n = np.linalg.lstsq(
         np.c_[np.arange(front, front_last), np.ones(front_last - front)],
         trend[front:front_last])[0]
-    trend[:front] = (np.arange(0, front) * np.c_[k] + np.c_[n]).T
+    extra = (np.arange(0, front) * np.c_[k] + np.c_[n]).T
+    if trend.ndim == 1:
+        extra = extra.squeeze()
+    trend[:front] = extra
 
     k, n = np.linalg.lstsq(
         np.c_[np.arange(back_first, back), np.ones(back - back_first)],
         trend[back_first:back])[0]
-    trend[back + 1:] = (np.arange(back + 1, trend.shape[0]) * np.c_[k] + np.c_[n]).T
+    extra = (np.arange(back + 1, trend.shape[0]) * np.c_[k] + np.c_[n]).T
+    if trend.ndim == 1:
+        extra = extra.squeeze()
+    trend[back + 1:] = extra
 
     return trend

{"golden_diff": "diff --git a/statsmodels/tsa/seasonal.py b/statsmodels/tsa/seasonal.py\n--- a/statsmodels/tsa/seasonal.py\n+++ b/statsmodels/tsa/seasonal.py\n@@ -34,12 +34,18 @@\n     k, n = np.linalg.lstsq(\n         np.c_[np.arange(front, front_last), np.ones(front_last - front)],\n         trend[front:front_last])[0]\n-    trend[:front] = (np.arange(0, front) * np.c_[k] + np.c_[n]).T\n+    extra = (np.arange(0, front) * np.c_[k] + np.c_[n]).T\n+    if trend.ndim == 1:\n+        extra = extra.squeeze()\n+    trend[:front] = extra\n \n     k, n = np.linalg.lstsq(\n         np.c_[np.arange(back_first, back), np.ones(back - back_first)],\n         trend[back_first:back])[0]\n-    trend[back + 1:] = (np.arange(back + 1, trend.shape[0]) * np.c_[k] + np.c_[n]).T\n+    extra = (np.arange(back + 1, trend.shape[0]) * np.c_[k] + np.c_[n]).T\n+    if trend.ndim == 1:\n+        extra = extra.squeeze()\n+    trend[back + 1:] = extra\n \n     return trend\n", "issue": "Issue in removing nan's from the trend variable\nHi,\r\nI am trying to use your code given in the link: https://github.com/statsmodels/statsmodels/blob/master/statsmodels/tsa/seasonal.py\r\nto remove the nan's which occur due to the moving averages. When i put the variable extrapolate_trend >0 then i get a value error saying: \r\nValueError: could not broadcast input array from shape (26,1) into shape (26)\r\nI want to extrapolate the trend values for a time series at a week level\n", "before_files": [{"content": "\"\"\"\nSeasonal Decomposition by Moving Averages\n\"\"\"\nfrom statsmodels.compat.python import lmap, range, iteritems\nimport numpy as np\nfrom pandas.core.nanops import nanmean as pd_nanmean\nfrom .filters._utils import (_maybe_get_pandas_wrapper_freq,\n                             _maybe_get_pandas_wrapper)\nfrom .filters.filtertools import convolution_filter\nfrom statsmodels.tsa.tsatools import freq_to_period\n\n\ndef seasonal_mean(x, freq):\n    \"\"\"\n    Return means for each period in x. freq is an int that gives the\n    number of periods per cycle. E.g., 12 for monthly. NaNs are ignored\n    in the mean.\n    \"\"\"\n    return np.array([pd_nanmean(x[i::freq], axis=0) for i in range(freq)])\n\n\ndef _extrapolate_trend(trend, npoints):\n    \"\"\"\n    Replace nan values on trend's end-points with least-squares extrapolated\n    values with regression considering npoints closest defined points.\n    \"\"\"\n    front = next(i for i, vals in enumerate(trend)\n                 if not np.any(np.isnan(vals)))\n    back = trend.shape[0] - 1 - next(i for i, vals in enumerate(trend[::-1])\n                                     if not np.any(np.isnan(vals)))\n    front_last = min(front + npoints, back)\n    back_first = max(front, back - npoints)\n\n    k, n = np.linalg.lstsq(\n        np.c_[np.arange(front, front_last), np.ones(front_last - front)],\n        trend[front:front_last])[0]\n    trend[:front] = (np.arange(0, front) * np.c_[k] + np.c_[n]).T\n\n    k, n = np.linalg.lstsq(\n        np.c_[np.arange(back_first, back), np.ones(back - back_first)],\n        trend[back_first:back])[0]\n    trend[back + 1:] = (np.arange(back + 1, trend.shape[0]) * np.c_[k] + np.c_[n]).T\n\n    return trend\n\n\ndef seasonal_decompose(x, model=\"additive\", filt=None, freq=None, two_sided=True,\n                       extrapolate_trend=0):\n    \"\"\"\n    Seasonal decomposition using moving averages\n\n    Parameters\n    ----------\n    x : array-like\n        Time series. If 2d, individual series are in columns.\n    model : str {\"additive\", \"multiplicative\"}\n        Type of seasonal component. Abbreviations are accepted.\n    filt : array-like\n        The filter coefficients for filtering out the seasonal component.\n        The concrete moving average method used in filtering is determined by two_sided.\n    freq : int, optional\n        Frequency of the series. Must be used if x is not a pandas object.\n        Overrides default periodicity of x if x is a pandas\n        object with a timeseries index.\n    two_sided : bool\n        The moving average method used in filtering.\n        If True (default), a centered moving average is computed using the filt.\n        If False, the filter coefficients are for past values only.\n    extrapolate_trend : int or 'freq', optional\n        If set to > 0, the trend resulting from the convolution is\n        linear least-squares extrapolated on both ends (or the single one\n        if two_sided is False) considering this many (+1) closest points.\n        If set to 'freq', use `freq` closest points. Setting this parameter\n        results in no NaN values in trend or resid components.\n\n    Returns\n    -------\n    results : obj\n        A object with seasonal, trend, and resid attributes.\n\n    Notes\n    -----\n    This is a naive decomposition. More sophisticated methods should\n    be preferred.\n\n    The additive model is Y[t] = T[t] + S[t] + e[t]\n\n    The multiplicative model is Y[t] = T[t] * S[t] * e[t]\n\n    The seasonal component is first removed by applying a convolution\n    filter to the data. The average of this smoothed series for each\n    period is the returned seasonal component.\n\n    See Also\n    --------\n    statsmodels.tsa.filters.bk_filter.bkfilter\n    statsmodels.tsa.filters.cf_filter.xffilter\n    statsmodels.tsa.filters.hp_filter.hpfilter\n    statsmodels.tsa.filters.convolution_filter\n    \"\"\"\n    if freq is None:\n        _pandas_wrapper, pfreq = _maybe_get_pandas_wrapper_freq(x)\n    else:\n        _pandas_wrapper = _maybe_get_pandas_wrapper(x)\n        pfreq = None\n    x = np.asanyarray(x).squeeze()\n    nobs = len(x)\n\n    if not np.all(np.isfinite(x)):\n        raise ValueError(\"This function does not handle missing values\")\n    if model.startswith('m'):\n        if np.any(x <= 0):\n            raise ValueError(\"Multiplicative seasonality is not appropriate \"\n                             \"for zero and negative values\")\n\n    if freq is None:\n        if pfreq is not None:\n            pfreq = freq_to_period(pfreq)\n            freq = pfreq\n        else:\n            raise ValueError(\"You must specify a freq or x must be a \"\n                             \"pandas object with a timeseries index with \"\n                             \"a freq not set to None\")\n\n    if filt is None:\n        if freq % 2 == 0:  # split weights at ends\n            filt = np.array([.5] + [1] * (freq - 1) + [.5]) / freq\n        else:\n            filt = np.repeat(1./freq, freq)\n\n    nsides = int(two_sided) + 1\n    trend = convolution_filter(x, filt, nsides)\n\n    if extrapolate_trend == 'freq':\n        extrapolate_trend = freq - 1\n\n    if extrapolate_trend > 0:\n        trend = _extrapolate_trend(trend, extrapolate_trend + 1)\n\n    if model.startswith('m'):\n        detrended = x / trend\n    else:\n        detrended = x - trend\n\n    period_averages = seasonal_mean(detrended, freq)\n\n    if model.startswith('m'):\n        period_averages /= np.mean(period_averages, axis=0)\n    else:\n        period_averages -= np.mean(period_averages, axis=0)\n\n    seasonal = np.tile(period_averages.T, nobs // freq + 1).T[:nobs]\n\n    if model.startswith('m'):\n        resid = x / seasonal / trend\n    else:\n        resid = detrended - seasonal\n\n    results = lmap(_pandas_wrapper, [seasonal, trend, resid, x])\n    return DecomposeResult(seasonal=results[0], trend=results[1],\n                           resid=results[2], observed=results[3])\n\n\nclass DecomposeResult(object):\n    def __init__(self, **kwargs):\n        for key, value in iteritems(kwargs):\n            setattr(self, key, value)\n        self.nobs = len(self.observed)\n\n    def plot(self):\n        from statsmodels.graphics.utils import _import_mpl\n        plt = _import_mpl()\n        fig, axes = plt.subplots(4, 1, sharex=True)\n        if hasattr(self.observed, 'plot'):  # got pandas use it\n            self.observed.plot(ax=axes[0], legend=False)\n            axes[0].set_ylabel('Observed')\n            self.trend.plot(ax=axes[1], legend=False)\n            axes[1].set_ylabel('Trend')\n            self.seasonal.plot(ax=axes[2], legend=False)\n            axes[2].set_ylabel('Seasonal')\n            self.resid.plot(ax=axes[3], legend=False)\n            axes[3].set_ylabel('Residual')\n        else:\n            axes[0].plot(self.observed)\n            axes[0].set_ylabel('Observed')\n            axes[1].plot(self.trend)\n            axes[1].set_ylabel('Trend')\n            axes[2].plot(self.seasonal)\n            axes[2].set_ylabel('Seasonal')\n            axes[3].plot(self.resid)\n            axes[3].set_ylabel('Residual')\n            axes[3].set_xlabel('Time')\n            axes[3].set_xlim(0, self.nobs)\n\n        fig.tight_layout()\n        return fig\n\n\nif __name__ == \"__main__\":\n    x = np.array([-50, 175, 149, 214, 247, 237, 225, 329, 729, 809,\n                  530, 489, 540, 457, 195, 176, 337, 239, 128, 102,\n                  232, 429, 3, 98, 43, -141, -77, -13, 125, 361, -45, 184])\n    results = seasonal_decompose(x, freq=4)\n\n    from pandas import DataFrame, DatetimeIndex\n    data = DataFrame(x, DatetimeIndex(start='1/1/1951',\n                                      periods=len(x),\n                                      freq='Q'))\n\n    res = seasonal_decompose(data)\n\n", "path": "statsmodels/tsa/seasonal.py"}], "after_files": [{"content": "\"\"\"\nSeasonal Decomposition by Moving Averages\n\"\"\"\nfrom statsmodels.compat.python import lmap, range, iteritems\nimport numpy as np\nfrom pandas.core.nanops import nanmean as pd_nanmean\nfrom .filters._utils import (_maybe_get_pandas_wrapper_freq,\n                             _maybe_get_pandas_wrapper)\nfrom .filters.filtertools import convolution_filter\nfrom statsmodels.tsa.tsatools import freq_to_period\n\n\ndef seasonal_mean(x, freq):\n    \"\"\"\n    Return means for each period in x. freq is an int that gives the\n    number of periods per cycle. E.g., 12 for monthly. NaNs are ignored\n    in the mean.\n    \"\"\"\n    return np.array([pd_nanmean(x[i::freq], axis=0) for i in range(freq)])\n\n\ndef _extrapolate_trend(trend, npoints):\n    \"\"\"\n    Replace nan values on trend's end-points with least-squares extrapolated\n    values with regression considering npoints closest defined points.\n    \"\"\"\n    front = next(i for i, vals in enumerate(trend)\n                 if not np.any(np.isnan(vals)))\n    back = trend.shape[0] - 1 - next(i for i, vals in enumerate(trend[::-1])\n                                     if not np.any(np.isnan(vals)))\n    front_last = min(front + npoints, back)\n    back_first = max(front, back - npoints)\n\n    k, n = np.linalg.lstsq(\n        np.c_[np.arange(front, front_last), np.ones(front_last - front)],\n        trend[front:front_last])[0]\n    extra = (np.arange(0, front) * np.c_[k] + np.c_[n]).T\n    if trend.ndim == 1:\n        extra = extra.squeeze()\n    trend[:front] = extra\n\n    k, n = np.linalg.lstsq(\n        np.c_[np.arange(back_first, back), np.ones(back - back_first)],\n        trend[back_first:back])[0]\n    extra = (np.arange(back + 1, trend.shape[0]) * np.c_[k] + np.c_[n]).T\n    if trend.ndim == 1:\n        extra = extra.squeeze()\n    trend[back + 1:] = extra\n\n    return trend\n\n\ndef seasonal_decompose(x, model=\"additive\", filt=None, freq=None, two_sided=True,\n                       extrapolate_trend=0):\n    \"\"\"\n    Seasonal decomposition using moving averages\n\n    Parameters\n    ----------\n    x : array-like\n        Time series. If 2d, individual series are in columns.\n    model : str {\"additive\", \"multiplicative\"}\n        Type of seasonal component. Abbreviations are accepted.\n    filt : array-like\n        The filter coefficients for filtering out the seasonal component.\n        The concrete moving average method used in filtering is determined by two_sided.\n    freq : int, optional\n        Frequency of the series. Must be used if x is not a pandas object.\n        Overrides default periodicity of x if x is a pandas\n        object with a timeseries index.\n    two_sided : bool\n        The moving average method used in filtering.\n        If True (default), a centered moving average is computed using the filt.\n        If False, the filter coefficients are for past values only.\n    extrapolate_trend : int or 'freq', optional\n        If set to > 0, the trend resulting from the convolution is\n        linear least-squares extrapolated on both ends (or the single one\n        if two_sided is False) considering this many (+1) closest points.\n        If set to 'freq', use `freq` closest points. Setting this parameter\n        results in no NaN values in trend or resid components.\n\n    Returns\n    -------\n    results : obj\n        A object with seasonal, trend, and resid attributes.\n\n    Notes\n    -----\n    This is a naive decomposition. More sophisticated methods should\n    be preferred.\n\n    The additive model is Y[t] = T[t] + S[t] + e[t]\n\n    The multiplicative model is Y[t] = T[t] * S[t] * e[t]\n\n    The seasonal component is first removed by applying a convolution\n    filter to the data. The average of this smoothed series for each\n    period is the returned seasonal component.\n\n    See Also\n    --------\n    statsmodels.tsa.filters.bk_filter.bkfilter\n    statsmodels.tsa.filters.cf_filter.xffilter\n    statsmodels.tsa.filters.hp_filter.hpfilter\n    statsmodels.tsa.filters.convolution_filter\n    \"\"\"\n    if freq is None:\n        _pandas_wrapper, pfreq = _maybe_get_pandas_wrapper_freq(x)\n    else:\n        _pandas_wrapper = _maybe_get_pandas_wrapper(x)\n        pfreq = None\n    x = np.asanyarray(x).squeeze()\n    nobs = len(x)\n\n    if not np.all(np.isfinite(x)):\n        raise ValueError(\"This function does not handle missing values\")\n    if model.startswith('m'):\n        if np.any(x <= 0):\n            raise ValueError(\"Multiplicative seasonality is not appropriate \"\n                             \"for zero and negative values\")\n\n    if freq is None:\n        if pfreq is not None:\n            pfreq = freq_to_period(pfreq)\n            freq = pfreq\n        else:\n            raise ValueError(\"You must specify a freq or x must be a \"\n                             \"pandas object with a timeseries index with \"\n                             \"a freq not set to None\")\n\n    if filt is None:\n        if freq % 2 == 0:  # split weights at ends\n            filt = np.array([.5] + [1] * (freq - 1) + [.5]) / freq\n        else:\n            filt = np.repeat(1./freq, freq)\n\n    nsides = int(two_sided) + 1\n    trend = convolution_filter(x, filt, nsides)\n\n    if extrapolate_trend == 'freq':\n        extrapolate_trend = freq - 1\n\n    if extrapolate_trend > 0:\n        trend = _extrapolate_trend(trend, extrapolate_trend + 1)\n\n    if model.startswith('m'):\n        detrended = x / trend\n    else:\n        detrended = x - trend\n\n    period_averages = seasonal_mean(detrended, freq)\n\n    if model.startswith('m'):\n        period_averages /= np.mean(period_averages, axis=0)\n    else:\n        period_averages -= np.mean(period_averages, axis=0)\n\n    seasonal = np.tile(period_averages.T, nobs // freq + 1).T[:nobs]\n\n    if model.startswith('m'):\n        resid = x / seasonal / trend\n    else:\n        resid = detrended - seasonal\n\n    results = lmap(_pandas_wrapper, [seasonal, trend, resid, x])\n    return DecomposeResult(seasonal=results[0], trend=results[1],\n                           resid=results[2], observed=results[3])\n\n\nclass DecomposeResult(object):\n    def __init__(self, **kwargs):\n        for key, value in iteritems(kwargs):\n            setattr(self, key, value)\n        self.nobs = len(self.observed)\n\n    def plot(self):\n        from statsmodels.graphics.utils import _import_mpl\n        plt = _import_mpl()\n        fig, axes = plt.subplots(4, 1, sharex=True)\n        if hasattr(self.observed, 'plot'):  # got pandas use it\n            self.observed.plot(ax=axes[0], legend=False)\n            axes[0].set_ylabel('Observed')\n            self.trend.plot(ax=axes[1], legend=False)\n            axes[1].set_ylabel('Trend')\n            self.seasonal.plot(ax=axes[2], legend=False)\n            axes[2].set_ylabel('Seasonal')\n            self.resid.plot(ax=axes[3], legend=False)\n            axes[3].set_ylabel('Residual')\n        else:\n            axes[0].plot(self.observed)\n            axes[0].set_ylabel('Observed')\n            axes[1].plot(self.trend)\n            axes[1].set_ylabel('Trend')\n            axes[2].plot(self.seasonal)\n            axes[2].set_ylabel('Seasonal')\n            axes[3].plot(self.resid)\n            axes[3].set_ylabel('Residual')\n            axes[3].set_xlabel('Time')\n            axes[3].set_xlim(0, self.nobs)\n\n        fig.tight_layout()\n        return fig\n\n\nif __name__ == \"__main__\":\n    x = np.array([-50, 175, 149, 214, 247, 237, 225, 329, 729, 809,\n                  530, 489, 540, 457, 195, 176, 337, 239, 128, 102,\n                  232, 429, 3, 98, 43, -141, -77, -13, 125, 361, -45, 184])\n    results = seasonal_decompose(x, freq=4)\n\n    from pandas import DataFrame, DatetimeIndex\n    data = DataFrame(x, DatetimeIndex(start='1/1/1951',\n                                      periods=len(x),\n                                      freq='Q'))\n\n    res = seasonal_decompose(data)\n\n", "path": "statsmodels/tsa/seasonal.py"}]}