Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1from statsmodels.compat.python import lrange, lzip 

2from statsmodels.compat.numpy import recarray_select 

3 

4import numpy as np 

5import numpy.lib.recfunctions as nprf 

6import pandas as pd 

7from pandas import DataFrame 

8from pandas.tseries import offsets 

9from pandas.tseries.frequencies import to_offset 

10 

11from statsmodels.tools.validation import int_like, bool_like, string_like 

12from statsmodels.tools.sm_exceptions import ValueWarning 

13from statsmodels.tools.data import _is_using_pandas, _is_recarray 

14from statsmodels.tools.validation import array_like 

15 

16 

17def add_trend(x, trend="c", prepend=False, has_constant='skip'): 

18 """ 

19 Add a trend and/or constant to an array. 

20 

21 Parameters 

22 ---------- 

23 x : array_like 

24 Original array of data. 

25 trend : str {'n', 'c', 't', 'ct', 'ctt'} 

26 The trend to add. 

27 

28 * 'n' add no trend. 

29 * 'c' add constant only. 

30 * 't' add trend only. 

31 * 'ct' add constant and linear trend. 

32 * 'ctt' add constant and linear and quadratic trend. 

33 prepend : bool 

34 If True, prepends the new data to the columns of X. 

35 has_constant : str {'raise', 'add', 'skip'} 

36 Controls what happens when trend is 'c' and a constant column already 

37 exists in x. 'raise' will raise an error. 'add' will add a column of 

38 1s. 'skip' will return the data without change. 'skip' is the default. 

39 

40 Returns 

41 ------- 

42 array_like 

43 The original data with the additional trend columns. If x is a 

44 recarray or pandas Series or DataFrame, then the trend column names 

45 are 'const', 'trend' and 'trend_squared'. 

46 

47 See Also 

48 -------- 

49 statsmodels.tools.tools.add_constant 

50 Add a constant column to an array. 

51 

52 Notes 

53 ----- 

54 Returns columns as ['ctt','ct','c'] whenever applicable. There is currently 

55 no checking for an existing trend. 

56 """ 

57 prepend = bool_like(prepend, 'prepend') 

58 trend = string_like(trend, 'trend', options=('n', 'c', 't', 'ct', 'ctt')) 

59 has_constant = string_like(has_constant, 'has_constant', 

60 options=('raise', 'add', 'skip')) 

61 

62 # TODO: could be generalized for trend of aribitrary order 

63 columns = ['const', 'trend', 'trend_squared'] 

64 if trend == 'n': 

65 return x.copy() 

66 elif trend == "c": # handles structured arrays 

67 columns = columns[:1] 

68 trendorder = 0 

69 elif trend == "ct" or trend == "t": 

70 columns = columns[:2] 

71 if trend == "t": 

72 columns = columns[1:2] 

73 trendorder = 1 

74 elif trend == "ctt": 

75 trendorder = 2 

76 

77 is_recarray = _is_recarray(x) 

78 is_pandas = _is_using_pandas(x, None) or is_recarray 

79 if is_pandas or is_recarray: 

80 if is_recarray: 

81 # deprecated: remove recarray support after 0.12 

82 import warnings 

83 from statsmodels.tools.sm_exceptions import recarray_warning 

84 warnings.warn(recarray_warning, FutureWarning) 

85 

86 descr = x.dtype.descr 

87 x = pd.DataFrame.from_records(x) 

88 elif isinstance(x, pd.Series): 

89 x = pd.DataFrame(x) 

90 else: 

91 x = x.copy() 

92 else: 

93 x = np.asanyarray(x) 

94 

95 nobs = len(x) 

96 trendarr = np.vander(np.arange(1, nobs + 1, dtype=np.float64), trendorder + 1) 

97 # put in order ctt 

98 trendarr = np.fliplr(trendarr) 

99 if trend == "t": 

100 trendarr = trendarr[:, 1] 

101 

102 if "c" in trend: 

103 if is_pandas or is_recarray: 

104 # Mixed type protection 

105 def safe_is_const(s): 

106 try: 

107 return np.ptp(s) == 0.0 and np.any(s != 0.0) 

108 except: 

109 return False 

110 col_const = x.apply(safe_is_const, 0) 

111 else: 

112 ptp0 = np.ptp(np.asanyarray(x), axis=0) 

113 col_is_const = ptp0 == 0 

114 nz_const = col_is_const & (x[0] != 0) 

115 col_const = nz_const 

116 

117 if np.any(col_const): 

118 if has_constant == 'raise': 

119 msg = "x contains a constant. Adding a constant with " \ 

120 "trend='{0}' is not allowed.".format(trend) 

121 raise ValueError(msg) 

122 elif has_constant == 'skip': 

123 columns = columns[1:] 

124 trendarr = trendarr[:, 1:] 

125 

126 order = 1 if prepend else -1 

127 if is_recarray or is_pandas: 

128 trendarr = pd.DataFrame(trendarr, index=x.index, columns=columns) 

129 x = [trendarr, x] 

130 x = pd.concat(x[::order], 1) 

131 else: 

132 x = [trendarr, x] 

133 x = np.column_stack(x[::order]) 

134 

135 if is_recarray: 

136 x = x.to_records(index=False) 

137 new_descr = x.dtype.descr 

138 extra_col = len(new_descr) - len(descr) 

139 if prepend: 

140 descr = new_descr[:extra_col] + descr 

141 else: 

142 descr = descr + new_descr[-extra_col:] 

143 

144 x = x.astype(np.dtype(descr)) 

145 

146 return x 

147 

148 

149def add_lag(x, col=None, lags=1, drop=False, insert=True): 

150 """ 

151 Returns an array with lags included given an array. 

152 

153 Parameters 

154 ---------- 

155 x : array_like 

156 An array or NumPy ndarray subclass. Can be either a 1d or 2d array with 

157 observations in columns. 

158 col : 'string', int, or None 

159 If data is a structured array or a recarray, `col` can be a string 

160 that is the name of the column containing the variable. Or `col` can 

161 be an int of the zero-based column index. If it's a 1d array `col` 

162 can be None. 

163 lags : int 

164 The number of lags desired. 

165 drop : bool 

166 Whether to keep the contemporaneous variable for the data. 

167 insert : bool or int 

168 If True, inserts the lagged values after `col`. If False, appends 

169 the data. If int inserts the lags at int. 

170 

171 Returns 

172 ------- 

173 array : ndarray 

174 Array with lags 

175 

176 Examples 

177 -------- 

178 

179 >>> import statsmodels.api as sm 

180 >>> data = sm.datasets.macrodata.load(as_pandas=False) 

181 >>> data = data.data[['year','quarter','realgdp','cpi']] 

182 >>> data = sm.tsa.add_lag(data, 'realgdp', lags=2) 

183 

184 Notes 

185 ----- 

186 Trims the array both forward and backward, so that the array returned 

187 so that the length of the returned array is len(`X`) - lags. The lags are 

188 returned in increasing order, ie., t-1,t-2,...,t-lags 

189 """ 

190 lags = int_like(lags, 'lags') 

191 drop = bool_like(drop, 'drop') 

192 

193 if x.dtype.names: 

194 names = x.dtype.names 

195 if not col and np.squeeze(x).ndim > 1: 

196 raise IndexError("col is None and the input array is not 1d") 

197 elif len(names) == 1: 

198 col = names[0] 

199 if isinstance(col, int): 

200 col = x.dtype.names[col] 

201 

202 contemp = x[col] 

203 

204 # make names for lags 

205 tmp_names = [col + '_'+'L(%i)' % i for i in range(1, lags+1)] 

206 ndlags = lagmat(contemp, maxlag=lags, trim='Both') 

207 

208 # get index for return 

209 if insert is True: 

210 ins_idx = list(names).index(col) + 1 

211 elif insert is False: 

212 ins_idx = len(names) + 1 

213 else: # insert is an int 

214 if insert > len(names): 

215 import warnings 

216 warnings.warn("insert > number of variables, inserting at the" 

217 " last position", ValueWarning) 

218 ins_idx = insert 

219 

220 first_names = list(names[:ins_idx]) 

221 last_names = list(names[ins_idx:]) 

222 

223 if drop: 

224 if col in first_names: 

225 first_names.pop(first_names.index(col)) 

226 else: 

227 last_names.pop(last_names.index(col)) 

228 

229 if first_names: # only do this if x is not "empty" 

230 # Workaround to avoid NumPy FutureWarning 

231 _x = recarray_select(x, first_names) 

232 first_arr = nprf.append_fields(_x[lags:], tmp_names, ndlags.T, 

233 usemask=False) 

234 

235 else: 

236 first_arr = np.zeros(len(x)-lags, dtype=lzip(tmp_names, 

237 (x[col].dtype,)*lags)) 

238 for i,name in enumerate(tmp_names): 

239 first_arr[name] = ndlags[:,i] 

240 if last_names: 

241 return nprf.append_fields(first_arr, last_names, 

242 [x[name][lags:] for name in last_names], usemask=False) 

243 else: # lags for last variable 

244 return first_arr 

245 

246 else: # we have an ndarray 

247 

248 if x.ndim == 1: # make 2d if 1d 

249 x = x[:,None] 

250 if col is None: 

251 col = 0 

252 

253 # handle negative index 

254 if col < 0: 

255 col = x.shape[1] + col 

256 

257 contemp = x[:,col] 

258 

259 if insert is True: 

260 ins_idx = col + 1 

261 elif insert is False: 

262 ins_idx = x.shape[1] 

263 else: 

264 if insert < 0: # handle negative index 

265 insert = x.shape[1] + insert + 1 

266 if insert > x.shape[1]: 

267 insert = x.shape[1] 

268 import warnings 

269 warnings.warn("insert > number of variables, inserting at the" 

270 " last position", ValueWarning) 

271 ins_idx = insert 

272 

273 ndlags = lagmat(contemp, lags, trim='Both') 

274 first_cols = lrange(ins_idx) 

275 last_cols = lrange(ins_idx,x.shape[1]) 

276 if drop: 

277 if col in first_cols: 

278 first_cols.pop(first_cols.index(col)) 

279 else: 

280 last_cols.pop(last_cols.index(col)) 

281 return np.column_stack((x[lags:,first_cols],ndlags, 

282 x[lags:,last_cols])) 

283 

284 

285def detrend(x, order=1, axis=0): 

286 """ 

287 Detrend an array with a trend of given order along axis 0 or 1. 

288 

289 Parameters 

290 ---------- 

291 x : array_like, 1d or 2d 

292 Data, if 2d, then each row or column is independently detrended with 

293 the same trendorder, but independent trend estimates. 

294 order : int 

295 The polynomial order of the trend, zero is constant, one is 

296 linear trend, two is quadratic trend. 

297 axis : int 

298 Axis can be either 0, observations by rows, or 1, observations by 

299 columns. 

300 

301 Returns 

302 ------- 

303 ndarray 

304 The detrended series is the residual of the linear regression of the 

305 data on the trend of given order. 

306 """ 

307 order = int_like(order, 'order') 

308 axis = int_like(axis, 'axis') 

309 

310 if x.ndim == 2 and int(axis) == 1: 

311 x = x.T 

312 elif x.ndim > 2: 

313 raise NotImplementedError('x.ndim > 2 is not implemented until it is needed') 

314 

315 nobs = x.shape[0] 

316 if order == 0: 

317 # Special case demean 

318 resid = x - x.mean(axis=0) 

319 else: 

320 trends = np.vander(np.arange(float(nobs)), N=order + 1) 

321 beta = np.linalg.pinv(trends).dot(x) 

322 resid = x - np.dot(trends, beta) 

323 

324 if x.ndim == 2 and int(axis) == 1: 

325 resid = resid.T 

326 

327 return resid 

328 

329 

330def lagmat(x, maxlag, trim='forward', original='ex', use_pandas=False): 

331 """ 

332 Create 2d array of lags. 

333 

334 Parameters 

335 ---------- 

336 x : array_like 

337 Data; if 2d, observation in rows and variables in columns. 

338 maxlag : int 

339 All lags from zero to maxlag are included. 

340 trim : {'forward', 'backward', 'both', 'none', None} 

341 The trimming method to use. 

342 

343 * 'forward' : trim invalid observations in front. 

344 * 'backward' : trim invalid initial observations. 

345 * 'both' : trim invalid observations on both sides. 

346 * 'none', None : no trimming of observations. 

347 original : {'ex','sep','in'} 

348 How the original is treated. 

349 

350 * 'ex' : drops the original array returning only the lagged values. 

351 * 'in' : returns the original array and the lagged values as a single 

352 array. 

353 * 'sep' : returns a tuple (original array, lagged values). The original 

354 array is truncated to have the same number of rows as 

355 the returned lagmat. 

356 use_pandas : bool 

357 If true, returns a DataFrame when the input is a pandas 

358 Series or DataFrame. If false, return numpy ndarrays. 

359 

360 Returns 

361 ------- 

362 lagmat : ndarray 

363 The array with lagged observations. 

364 y : ndarray, optional 

365 Only returned if original == 'sep'. 

366 

367 Notes 

368 ----- 

369 When using a pandas DataFrame or Series with use_pandas=True, trim can only 

370 be 'forward' or 'both' since it is not possible to consistently extend 

371 index values. 

372 

373 Examples 

374 -------- 

375 >>> from statsmodels.tsa.tsatools import lagmat 

376 >>> import numpy as np 

377 >>> X = np.arange(1,7).reshape(-1,2) 

378 >>> lagmat(X, maxlag=2, trim="forward", original='in') 

379 array([[ 1., 2., 0., 0., 0., 0.], 

380 [ 3., 4., 1., 2., 0., 0.], 

381 [ 5., 6., 3., 4., 1., 2.]]) 

382 

383 >>> lagmat(X, maxlag=2, trim="backward", original='in') 

384 array([[ 5., 6., 3., 4., 1., 2.], 

385 [ 0., 0., 5., 6., 3., 4.], 

386 [ 0., 0., 0., 0., 5., 6.]]) 

387 

388 >>> lagmat(X, maxlag=2, trim="both", original='in') 

389 array([[ 5., 6., 3., 4., 1., 2.]]) 

390 

391 >>> lagmat(X, maxlag=2, trim="none", original='in') 

392 array([[ 1., 2., 0., 0., 0., 0.], 

393 [ 3., 4., 1., 2., 0., 0.], 

394 [ 5., 6., 3., 4., 1., 2.], 

395 [ 0., 0., 5., 6., 3., 4.], 

396 [ 0., 0., 0., 0., 5., 6.]]) 

397 """ 

398 maxlag = int_like(maxlag, 'maxlag') 

399 use_pandas = bool_like(use_pandas, 'use_pandas') 

400 trim = string_like(trim, 'trim', optional=True, 

401 options=('forward', 'backward', 'both', 'none')) 

402 original = string_like(original, 'original', options=('ex', 'sep', 'in')) 

403 

404 # TODO: allow list of lags additional to maxlag 

405 orig = x 

406 x = array_like(x, 'x', ndim=2, dtype=None) 

407 is_pandas = _is_using_pandas(orig, None) and use_pandas 

408 trim = 'none' if trim is None else trim 

409 trim = trim.lower() 

410 if is_pandas and trim in ('none', 'backward'): 

411 raise ValueError("trim cannot be 'none' or 'forward' when used on " 

412 "Series or DataFrames") 

413 

414 dropidx = 0 

415 nobs, nvar = x.shape 

416 if original in ['ex', 'sep']: 

417 dropidx = nvar 

418 if maxlag >= nobs: 

419 raise ValueError("maxlag should be < nobs") 

420 lm = np.zeros((nobs + maxlag, nvar * (maxlag + 1))) 

421 for k in range(0, int(maxlag + 1)): 

422 lm[maxlag - k:nobs + maxlag - k, 

423 nvar * (maxlag - k):nvar * (maxlag - k + 1)] = x 

424 

425 if trim in ('none', 'forward'): 

426 startobs = 0 

427 elif trim in ('backward', 'both'): 

428 startobs = maxlag 

429 else: 

430 raise ValueError('trim option not valid') 

431 

432 if trim in ('none', 'backward'): 

433 stopobs = len(lm) 

434 else: 

435 stopobs = nobs 

436 

437 if is_pandas: 

438 x = orig 

439 x_columns = x.columns if isinstance(x, DataFrame) else [x.name] 

440 columns = [str(col) for col in x_columns] 

441 for lag in range(maxlag): 

442 lag_str = str(lag + 1) 

443 columns.extend([str(col) + '.L.' + lag_str for col in x_columns]) 

444 lm = DataFrame(lm[:stopobs], index=x.index, columns=columns) 

445 lags = lm.iloc[startobs:] 

446 if original in ('sep', 'ex'): 

447 leads = lags[x_columns] 

448 lags = lags.drop(x_columns, 1) 

449 else: 

450 lags = lm[startobs:stopobs, dropidx:] 

451 if original == 'sep': 

452 leads = lm[startobs:stopobs, :dropidx] 

453 

454 if original == 'sep': 

455 return lags, leads 

456 else: 

457 return lags 

458 

459 

460def lagmat2ds(x, maxlag0, maxlagex=None, dropex=0, trim='forward', 

461 use_pandas=False): 

462 """ 

463 Generate lagmatrix for 2d array, columns arranged by variables. 

464 

465 Parameters 

466 ---------- 

467 x : array_like 

468 Data, 2d. Observations in rows and variables in columns. 

469 maxlag0 : int 

470 The first variable all lags from zero to maxlag are included. 

471 maxlagex : {None, int} 

472 The max lag for all other variables all lags from zero to maxlag are 

473 included. 

474 dropex : int 

475 Exclude first dropex lags from other variables. For all variables, 

476 except the first, lags from dropex to maxlagex are included. 

477 trim : str 

478 The trimming method to use. 

479 

480 * 'forward' : trim invalid observations in front. 

481 * 'backward' : trim invalid initial observations. 

482 * 'both' : trim invalid observations on both sides. 

483 * 'none' : no trimming of observations. 

484 use_pandas : bool 

485 If true, returns a DataFrame when the input is a pandas 

486 Series or DataFrame. If false, return numpy ndarrays. 

487 

488 Returns 

489 ------- 

490 ndarray 

491 The array with lagged observations, columns ordered by variable. 

492 

493 Notes 

494 ----- 

495 Inefficient implementation for unequal lags, implemented for convenience. 

496 """ 

497 maxlag0 = int_like(maxlag0, 'maxlag0') 

498 maxlagex = int_like(maxlagex, 'maxlagex', optional=True) 

499 trim = string_like(trim, 'trim', optional=True, 

500 options=('forward', 'backward', 'both', 'none')) 

501 if maxlagex is None: 

502 maxlagex = maxlag0 

503 maxlag = max(maxlag0, maxlagex) 

504 is_pandas = _is_using_pandas(x, None) 

505 

506 if x.ndim == 1: 

507 if is_pandas: 

508 x = pd.DataFrame(x) 

509 else: 

510 x = x[:, None] 

511 elif x.ndim == 0 or x.ndim > 2: 

512 raise ValueError('Only supports 1 and 2-dimensional data.') 

513 

514 nobs, nvar = x.shape 

515 

516 if is_pandas and use_pandas: 

517 lags = lagmat(x.iloc[:, 0], maxlag, trim=trim, 

518 original='in', use_pandas=True) 

519 lagsli = [lags.iloc[:, :maxlag0 + 1]] 

520 for k in range(1, nvar): 

521 lags = lagmat(x.iloc[:, k], maxlag, trim=trim, 

522 original='in', use_pandas=True) 

523 lagsli.append(lags.iloc[:, dropex:maxlagex + 1]) 

524 return pd.concat(lagsli, axis=1) 

525 elif is_pandas: 

526 x = np.asanyarray(x) 

527 

528 lagsli = [lagmat(x[:, 0], maxlag, trim=trim, original='in')[:, :maxlag0 + 1]] 

529 for k in range(1, nvar): 

530 lagsli.append(lagmat(x[:, k], maxlag, trim=trim, original='in')[:, dropex:maxlagex + 1]) 

531 return np.column_stack(lagsli) 

532 

533 

534def vec(mat): 

535 return mat.ravel('F') 

536 

537 

538def vech(mat): 

539 # Gets Fortran-order 

540 return mat.T.take(_triu_indices(len(mat))) 

541 

542 

543# tril/triu/diag, suitable for ndarray.take 

544 

545def _tril_indices(n): 

546 rows, cols = np.tril_indices(n) 

547 return rows * n + cols 

548 

549 

550def _triu_indices(n): 

551 rows, cols = np.triu_indices(n) 

552 return rows * n + cols 

553 

554 

555def _diag_indices(n): 

556 rows, cols = np.diag_indices(n) 

557 return rows * n + cols 

558 

559 

560def unvec(v): 

561 k = int(np.sqrt(len(v))) 

562 assert(k * k == len(v)) 

563 return v.reshape((k, k), order='F') 

564 

565 

566def unvech(v): 

567 # quadratic formula, correct fp error 

568 rows = .5 * (-1 + np.sqrt(1 + 8 * len(v))) 

569 rows = int(np.round(rows)) 

570 

571 result = np.zeros((rows, rows)) 

572 result[np.triu_indices(rows)] = v 

573 result = result + result.T 

574 

575 # divide diagonal elements by 2 

576 result[np.diag_indices(rows)] /= 2 

577 

578 return result 

579 

580 

581def duplication_matrix(n): 

582 """ 

583 Create duplication matrix D_n which satisfies vec(S) = D_n vech(S) for 

584 symmetric matrix S 

585 

586 Returns 

587 ------- 

588 D_n : ndarray 

589 """ 

590 n = int_like(n, 'n') 

591 tmp = np.eye(n * (n + 1) // 2) 

592 return np.array([unvech(x).ravel() for x in tmp]).T 

593 

594 

595def elimination_matrix(n): 

596 """ 

597 Create the elimination matrix L_n which satisfies vech(M) = L_n vec(M) for 

598 any matrix M 

599 

600 Parameters 

601 ---------- 

602 

603 Returns 

604 ------- 

605 """ 

606 n = int_like(n, 'n') 

607 vech_indices = vec(np.tril(np.ones((n, n)))) 

608 return np.eye(n * n)[vech_indices != 0] 

609 

610 

611def commutation_matrix(p, q): 

612 """ 

613 Create the commutation matrix K_{p,q} satisfying vec(A') = K_{p,q} vec(A) 

614 

615 Parameters 

616 ---------- 

617 p : int 

618 q : int 

619 

620 Returns 

621 ------- 

622 K : ndarray (pq x pq) 

623 """ 

624 p = int_like(p, 'p') 

625 q = int_like(q, 'q') 

626 

627 K = np.eye(p * q) 

628 indices = np.arange(p * q).reshape((p, q), order='F') 

629 return K.take(indices.ravel(), axis=0) 

630 

631 

632def _ar_transparams(params): 

633 """ 

634 Transforms params to induce stationarity/invertability. 

635 

636 Parameters 

637 ---------- 

638 params : array_like 

639 The AR coefficients 

640 

641 Reference 

642 --------- 

643 Jones(1980) 

644 """ 

645 newparams = np.tanh(params/2) 

646 tmp = np.tanh(params/2) 

647 for j in range(1,len(params)): 

648 a = newparams[j] 

649 for kiter in range(j): 

650 tmp[kiter] -= a * newparams[j-kiter-1] 

651 newparams[:j] = tmp[:j] 

652 return newparams 

653 

654 

655def _ar_invtransparams(params): 

656 """ 

657 Inverse of the Jones reparameterization 

658 

659 Parameters 

660 ---------- 

661 params : array_like 

662 The transformed AR coefficients 

663 """ 

664 params = params.copy() 

665 tmp = params.copy() 

666 for j in range(len(params)-1,0,-1): 

667 a = params[j] 

668 for kiter in range(j): 

669 tmp[kiter] = (params[kiter] + a * params[j-kiter-1])/\ 

670 (1-a**2) 

671 params[:j] = tmp[:j] 

672 invarcoefs = 2*np.arctanh(params) 

673 return invarcoefs 

674 

675 

676def _ma_transparams(params): 

677 """ 

678 Transforms params to induce stationarity/invertability. 

679 

680 Parameters 

681 ---------- 

682 params : ndarray 

683 The ma coeffecients of an (AR)MA model. 

684 

685 Reference 

686 --------- 

687 Jones(1980) 

688 """ 

689 newparams = ((1-np.exp(-params))/(1+np.exp(-params))).copy() 

690 tmp = ((1-np.exp(-params))/(1+np.exp(-params))).copy() 

691 

692 # levinson-durbin to get macf 

693 for j in range(1,len(params)): 

694 b = newparams[j] 

695 for kiter in range(j): 

696 tmp[kiter] += b * newparams[j-kiter-1] 

697 newparams[:j] = tmp[:j] 

698 return newparams 

699 

700 

701def _ma_invtransparams(macoefs): 

702 """ 

703 Inverse of the Jones reparameterization 

704 

705 Parameters 

706 ---------- 

707 params : ndarray 

708 The transformed MA coefficients 

709 """ 

710 tmp = macoefs.copy() 

711 for j in range(len(macoefs)-1,0,-1): 

712 b = macoefs[j] 

713 for kiter in range(j): 

714 tmp[kiter] = (macoefs[kiter]-b *macoefs[j-kiter-1])/(1-b**2) 

715 macoefs[:j] = tmp[:j] 

716 invmacoefs = -np.log((1-macoefs)/(1+macoefs)) 

717 return invmacoefs 

718 

719 

720def unintegrate_levels(x, d): 

721 """ 

722 Returns the successive differences needed to unintegrate the series. 

723 

724 Parameters 

725 ---------- 

726 x : array_like 

727 The original series 

728 d : int 

729 The number of differences of the differenced series. 

730 

731 Returns 

732 ------- 

733 y : array_like 

734 The increasing differences from 0 to d-1 of the first d elements 

735 of x. 

736 

737 See Also 

738 -------- 

739 unintegrate 

740 """ 

741 d = int_like(d, 'd') 

742 x = x[:d] 

743 return np.asarray([np.diff(x, d - i)[0] for i in range(d, 0, -1)]) 

744 

745 

746def unintegrate(x, levels): 

747 """ 

748 After taking n-differences of a series, return the original series 

749 

750 Parameters 

751 ---------- 

752 x : array_like 

753 The n-th differenced series 

754 levels : list 

755 A list of the first-value in each differenced series, for 

756 [first-difference, second-difference, ..., n-th difference] 

757 

758 Returns 

759 ------- 

760 y : array_like 

761 The original series de-differenced 

762 

763 Examples 

764 -------- 

765 >>> x = np.array([1, 3, 9., 19, 8.]) 

766 >>> levels = unintegrate_levels(x, 2) 

767 >>> levels 

768 array([ 1., 2.]) 

769 >>> unintegrate(np.diff(x, 2), levels) 

770 array([ 1., 3., 9., 19., 8.]) 

771 """ 

772 levels = list(levels)[:] # copy 

773 if len(levels) > 1: 

774 x0 = levels.pop(-1) 

775 return unintegrate(np.cumsum(np.r_[x0, x]), levels) 

776 x0 = levels[0] 

777 return np.cumsum(np.r_[x0, x]) 

778 

779 

780def freq_to_period(freq): 

781 """ 

782 Convert a pandas frequency to a periodicity 

783 

784 Parameters 

785 ---------- 

786 freq : str or offset 

787 Frequency to convert 

788 

789 Returns 

790 ------- 

791 period : int 

792 Periodicity of freq 

793 

794 Notes 

795 ----- 

796 Annual maps to 1, quarterly maps to 4, monthly to 12, weekly to 52. 

797 """ 

798 if not isinstance(freq, offsets.DateOffset): 

799 freq = to_offset(freq) # go ahead and standardize 

800 freq = freq.rule_code.upper() 

801 

802 if freq == 'A' or freq.startswith(('A-', 'AS-')): 

803 return 1 

804 elif freq == 'Q' or freq.startswith(('Q-', 'QS-')): 

805 return 4 

806 elif freq == 'M' or freq.startswith(('M-', 'MS')): 

807 return 12 

808 elif freq == 'W' or freq.startswith('W-'): 

809 return 52 

810 elif freq == 'D': 

811 return 7 

812 elif freq == 'B': 

813 return 5 

814 elif freq == 'H': 

815 return 24 

816 else: # pragma : no cover 

817 raise ValueError("freq {} not understood. Please report if you " 

818 "think this is in error.".format(freq)) 

819 

820 

821__all__ = ['lagmat', 'lagmat2ds','add_trend', 'duplication_matrix', 

822 'elimination_matrix', 'commutation_matrix', 

823 'vec', 'vech', 'unvec', 'unvech', 'freq_to_period']