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

1""" 

2SARIMAX tools. 

3 

4Author: Chad Fulton 

5License: BSD-3 

6""" 

7import numpy as np 

8 

9 

10def standardize_lag_order(order, title=None): 

11 """ 

12 Standardize lag order input. 

13 

14 Parameters 

15 ---------- 

16 order : int or array_like 

17 Maximum lag order (if integer) or iterable of specific lag orders. 

18 title : str, optional 

19 Description of the order (e.g. "autoregressive") to use in error 

20 messages. 

21 

22 Returns 

23 ------- 

24 order : int or list of int 

25 Maximum lag order if consecutive lag orders were specified, otherwise 

26 a list of integer lag orders. 

27 

28 Notes 

29 ----- 

30 It is ambiguous if order=[1] is meant to be a boolean list or 

31 a list of lag orders to include, but this is irrelevant because either 

32 interpretation gives the same result. 

33 

34 Order=[0] would be ambiguous, except that 0 is not a valid lag 

35 order to include, so there is no harm in interpreting as a boolean 

36 list, in which case it is the same as order=0, which seems like 

37 reasonable behavior. 

38 

39 Examples 

40 -------- 

41 >>> standardize_lag_order(3) 

42 3 

43 >>> standardize_lag_order(np.arange(1, 4)) 

44 3 

45 >>> standardize_lag_order([1, 3]) 

46 [1, 3] 

47 """ 

48 order = np.array(order) 

49 title = 'order' if title is None else '%s order' % title 

50 

51 # Only integer orders are valid 

52 if not np.all(order == order.astype(int)): 

53 raise ValueError('Invalid %s. Non-integer order (%s) given.' 

54 % (title, order)) 

55 order = order.astype(int) 

56 

57 # Only positive integers are valid 

58 if np.any(order < 0): 

59 raise ValueError('Terms in the %s cannot be negative.' % title) 

60 

61 # Try to squeeze out an irrelevant trailing dimension 

62 if order.ndim == 2 and order.shape[1] == 1: 

63 order = order[:, 0] 

64 elif order.ndim > 1: 

65 raise ValueError('Invalid %s. Must be an integer or' 

66 ' 1-dimensional array-like object (e.g. list,' 

67 ' ndarray, etc.). Got %s.' % (title, order)) 

68 

69 # Option 1: the typical integer response (implies including all 

70 # lags up through and including the value) 

71 if order.ndim == 0: 

72 order = order.item() 

73 elif len(order) == 0: 

74 order = 0 

75 else: 

76 # Option 2: boolean list 

77 has_zeros = (0 in order) 

78 has_multiple_ones = np.sum(order == 1) > 1 

79 has_gt_one = np.any(order > 1) 

80 if has_zeros or has_multiple_ones: 

81 if has_gt_one: 

82 raise ValueError('Invalid %s. Appears to be a boolean list' 

83 ' (since it contains a 0 element and/or' 

84 ' multiple elements) but also contains' 

85 ' elements greater than 1 like a list of' 

86 ' lag orders.' % title) 

87 order = (np.where(order == 1)[0] + 1) 

88 

89 # (Default) Option 3: list of lag orders to include 

90 else: 

91 order = np.sort(order) 

92 

93 # If we have an empty list, set order to zero 

94 if len(order) == 0: 

95 order = 0 

96 # If we actually were given consecutive lag orders, just use integer 

97 elif np.all(order == np.arange(1, len(order) + 1)): 

98 order = order[-1] 

99 # Otherwise, convert to list 

100 else: 

101 order = order.tolist() 

102 

103 # Check for duplicates 

104 has_duplicate = isinstance(order, list) and np.any(np.diff(order) == 0) 

105 if has_duplicate: 

106 raise ValueError('Invalid %s. Cannot have duplicate elements.' % title) 

107 

108 return order 

109 

110 

111def validate_basic(params, length, allow_infnan=False, title=None): 

112 """ 

113 Validate parameter vector for basic correctness. 

114 

115 Parameters 

116 ---------- 

117 params : array_like 

118 Array of parameters to validate. 

119 length : int 

120 Expected length of the parameter vector. 

121 allow_infnan : bool, optional 

122 Whether or not to allow `params` to contain -np.Inf, np.Inf, and 

123 np.nan. Default is False. 

124 title : str, optional 

125 Description of the parameters (e.g. "autoregressive") to use in error 

126 messages. 

127 

128 Returns 

129 ------- 

130 params : ndarray 

131 Array of validated parameters. 

132 

133 Notes 

134 ----- 

135 Basic check that the parameters are numeric and that they are the right 

136 shape. Optionally checks for NaN / infinite values. 

137 """ 

138 title = '' if title is None else ' for %s' % title 

139 

140 # Check for invalid type and coerce to non-integer 

141 try: 

142 params = np.array(params) * 1.0 

143 except TypeError: 

144 raise ValueError('Parameters vector%s includes invalid values.' 

145 % title) 

146 

147 # Check for NaN, inf 

148 if not allow_infnan and (np.any(np.isnan(params)) or 

149 np.any(np.isinf(params))): 

150 raise ValueError('Parameters vector%s includes NaN or Inf values.' 

151 % title) 

152 

153 params = np.atleast_1d(np.squeeze(params)) 

154 

155 # Check for right number of parameters 

156 if params.shape != (length,): 

157 plural = '' if length == 1 else 's' 

158 raise ValueError('Specification%s implies %d parameter%s, but' 

159 ' values with shape %s were provided.' 

160 % (title, length, plural, params.shape)) 

161 

162 return params