Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/pandas/core/indexes/timedeltas.py: 43%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

79 statements  

1""" implement the TimedeltaIndex """ 

2from __future__ import annotations 

3 

4from typing import TYPE_CHECKING 

5import warnings 

6 

7from pandas._libs import ( 

8 index as libindex, 

9 lib, 

10) 

11from pandas._libs.tslibs import ( 

12 Resolution, 

13 Timedelta, 

14 to_offset, 

15) 

16from pandas._libs.tslibs.timedeltas import disallow_ambiguous_unit 

17from pandas.util._exceptions import find_stack_level 

18 

19from pandas.core.dtypes.common import ( 

20 is_scalar, 

21 pandas_dtype, 

22) 

23from pandas.core.dtypes.generic import ABCSeries 

24 

25from pandas.core.arrays.timedeltas import TimedeltaArray 

26import pandas.core.common as com 

27from pandas.core.indexes.base import ( 

28 Index, 

29 maybe_extract_name, 

30) 

31from pandas.core.indexes.datetimelike import DatetimeTimedeltaMixin 

32from pandas.core.indexes.extension import inherit_names 

33 

34if TYPE_CHECKING: 

35 from pandas._typing import DtypeObj 

36 

37 

38@inherit_names( 

39 ["__neg__", "__pos__", "__abs__", "total_seconds", "round", "floor", "ceil"] 

40 + TimedeltaArray._field_ops, 

41 TimedeltaArray, 

42 wrap=True, 

43) 

44@inherit_names( 

45 [ 

46 "components", 

47 "to_pytimedelta", 

48 "sum", 

49 "std", 

50 "median", 

51 ], 

52 TimedeltaArray, 

53) 

54class TimedeltaIndex(DatetimeTimedeltaMixin): 

55 """ 

56 Immutable Index of timedelta64 data. 

57 

58 Represented internally as int64, and scalars returned Timedelta objects. 

59 

60 Parameters 

61 ---------- 

62 data : array-like (1-dimensional), optional 

63 Optional timedelta-like data to construct index with. 

64 unit : {'D', 'h', 'm', 's', 'ms', 'us', 'ns'}, optional 

65 The unit of ``data``. 

66 

67 .. deprecated:: 2.2.0 

68 Use ``pd.to_timedelta`` instead. 

69 

70 freq : str or pandas offset object, optional 

71 One of pandas date offset strings or corresponding objects. The string 

72 ``'infer'`` can be passed in order to set the frequency of the index as 

73 the inferred frequency upon creation. 

74 dtype : numpy.dtype or str, default None 

75 Valid ``numpy`` dtypes are ``timedelta64[ns]``, ``timedelta64[us]``, 

76 ``timedelta64[ms]``, and ``timedelta64[s]``. 

77 copy : bool 

78 Make a copy of input array. 

79 name : object 

80 Name to be stored in the index. 

81 

82 Attributes 

83 ---------- 

84 days 

85 seconds 

86 microseconds 

87 nanoseconds 

88 components 

89 inferred_freq 

90 

91 Methods 

92 ------- 

93 to_pytimedelta 

94 to_series 

95 round 

96 floor 

97 ceil 

98 to_frame 

99 mean 

100 

101 See Also 

102 -------- 

103 Index : The base pandas Index type. 

104 Timedelta : Represents a duration between two dates or times. 

105 DatetimeIndex : Index of datetime64 data. 

106 PeriodIndex : Index of Period data. 

107 timedelta_range : Create a fixed-frequency TimedeltaIndex. 

108 

109 Notes 

110 ----- 

111 To learn more about the frequency strings, please see `this link 

112 <https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#offset-aliases>`__. 

113 

114 Examples 

115 -------- 

116 >>> pd.TimedeltaIndex(['0 days', '1 days', '2 days', '3 days', '4 days']) 

117 TimedeltaIndex(['0 days', '1 days', '2 days', '3 days', '4 days'], 

118 dtype='timedelta64[ns]', freq=None) 

119 

120 We can also let pandas infer the frequency when possible. 

121 

122 >>> pd.TimedeltaIndex(np.arange(5) * 24 * 3600 * 1e9, freq='infer') 

123 TimedeltaIndex(['0 days', '1 days', '2 days', '3 days', '4 days'], 

124 dtype='timedelta64[ns]', freq='D') 

125 """ 

126 

127 _typ = "timedeltaindex" 

128 

129 _data_cls = TimedeltaArray 

130 

131 @property 

132 def _engine_type(self) -> type[libindex.TimedeltaEngine]: 

133 return libindex.TimedeltaEngine 

134 

135 _data: TimedeltaArray 

136 

137 # Use base class method instead of DatetimeTimedeltaMixin._get_string_slice 

138 _get_string_slice = Index._get_string_slice 

139 

140 # error: Signature of "_resolution_obj" incompatible with supertype 

141 # "DatetimeIndexOpsMixin" 

142 @property 

143 def _resolution_obj(self) -> Resolution | None: # type: ignore[override] 

144 return self._data._resolution_obj 

145 

146 # ------------------------------------------------------------------- 

147 # Constructors 

148 

149 def __new__( 

150 cls, 

151 data=None, 

152 unit=lib.no_default, 

153 freq=lib.no_default, 

154 closed=lib.no_default, 

155 dtype=None, 

156 copy: bool = False, 

157 name=None, 

158 ): 

159 if closed is not lib.no_default: 

160 # GH#52628 

161 warnings.warn( 

162 f"The 'closed' keyword in {cls.__name__} construction is " 

163 "deprecated and will be removed in a future version.", 

164 FutureWarning, 

165 stacklevel=find_stack_level(), 

166 ) 

167 

168 if unit is not lib.no_default: 

169 # GH#55499 

170 warnings.warn( 

171 f"The 'unit' keyword in {cls.__name__} construction is " 

172 "deprecated and will be removed in a future version. " 

173 "Use pd.to_timedelta instead.", 

174 FutureWarning, 

175 stacklevel=find_stack_level(), 

176 ) 

177 else: 

178 unit = None 

179 

180 name = maybe_extract_name(name, data, cls) 

181 

182 if is_scalar(data): 

183 cls._raise_scalar_data_error(data) 

184 

185 disallow_ambiguous_unit(unit) 

186 if dtype is not None: 

187 dtype = pandas_dtype(dtype) 

188 

189 if ( 

190 isinstance(data, TimedeltaArray) 

191 and freq is lib.no_default 

192 and (dtype is None or dtype == data.dtype) 

193 ): 

194 if copy: 

195 data = data.copy() 

196 return cls._simple_new(data, name=name) 

197 

198 if ( 

199 isinstance(data, TimedeltaIndex) 

200 and freq is lib.no_default 

201 and name is None 

202 and (dtype is None or dtype == data.dtype) 

203 ): 

204 if copy: 

205 return data.copy() 

206 else: 

207 return data._view() 

208 

209 # - Cases checked above all return/raise before reaching here - # 

210 

211 tdarr = TimedeltaArray._from_sequence_not_strict( 

212 data, freq=freq, unit=unit, dtype=dtype, copy=copy 

213 ) 

214 refs = None 

215 if not copy and isinstance(data, (ABCSeries, Index)): 

216 refs = data._references 

217 

218 return cls._simple_new(tdarr, name=name, refs=refs) 

219 

220 # ------------------------------------------------------------------- 

221 

222 def _is_comparable_dtype(self, dtype: DtypeObj) -> bool: 

223 """ 

224 Can we compare values of the given dtype to our own? 

225 """ 

226 return lib.is_np_dtype(dtype, "m") # aka self._data._is_recognized_dtype 

227 

228 # ------------------------------------------------------------------- 

229 # Indexing Methods 

230 

231 def get_loc(self, key): 

232 """ 

233 Get integer location for requested label 

234 

235 Returns 

236 ------- 

237 loc : int, slice, or ndarray[int] 

238 """ 

239 self._check_indexing_error(key) 

240 

241 try: 

242 key = self._data._validate_scalar(key, unbox=False) 

243 except TypeError as err: 

244 raise KeyError(key) from err 

245 

246 return Index.get_loc(self, key) 

247 

248 def _parse_with_reso(self, label: str): 

249 # the "with_reso" is a no-op for TimedeltaIndex 

250 parsed = Timedelta(label) 

251 return parsed, None 

252 

253 def _parsed_string_to_bounds(self, reso, parsed: Timedelta): 

254 # reso is unused, included to match signature of DTI/PI 

255 lbound = parsed.round(parsed.resolution_string) 

256 rbound = lbound + to_offset(parsed.resolution_string) - Timedelta(1, "ns") 

257 return lbound, rbound 

258 

259 # ------------------------------------------------------------------- 

260 

261 @property 

262 def inferred_type(self) -> str: 

263 return "timedelta64" 

264 

265 

266def timedelta_range( 

267 start=None, 

268 end=None, 

269 periods: int | None = None, 

270 freq=None, 

271 name=None, 

272 closed=None, 

273 *, 

274 unit: str | None = None, 

275) -> TimedeltaIndex: 

276 """ 

277 Return a fixed frequency TimedeltaIndex with day as the default. 

278 

279 Parameters 

280 ---------- 

281 start : str or timedelta-like, default None 

282 Left bound for generating timedeltas. 

283 end : str or timedelta-like, default None 

284 Right bound for generating timedeltas. 

285 periods : int, default None 

286 Number of periods to generate. 

287 freq : str, Timedelta, datetime.timedelta, or DateOffset, default 'D' 

288 Frequency strings can have multiples, e.g. '5h'. 

289 name : str, default None 

290 Name of the resulting TimedeltaIndex. 

291 closed : str, default None 

292 Make the interval closed with respect to the given frequency to 

293 the 'left', 'right', or both sides (None). 

294 unit : str, default None 

295 Specify the desired resolution of the result. 

296 

297 .. versionadded:: 2.0.0 

298 

299 Returns 

300 ------- 

301 TimedeltaIndex 

302 

303 Notes 

304 ----- 

305 Of the four parameters ``start``, ``end``, ``periods``, and ``freq``, 

306 exactly three must be specified. If ``freq`` is omitted, the resulting 

307 ``TimedeltaIndex`` will have ``periods`` linearly spaced elements between 

308 ``start`` and ``end`` (closed on both sides). 

309 

310 To learn more about the frequency strings, please see `this link 

311 <https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#offset-aliases>`__. 

312 

313 Examples 

314 -------- 

315 >>> pd.timedelta_range(start='1 day', periods=4) 

316 TimedeltaIndex(['1 days', '2 days', '3 days', '4 days'], 

317 dtype='timedelta64[ns]', freq='D') 

318 

319 The ``closed`` parameter specifies which endpoint is included. The default 

320 behavior is to include both endpoints. 

321 

322 >>> pd.timedelta_range(start='1 day', periods=4, closed='right') 

323 TimedeltaIndex(['2 days', '3 days', '4 days'], 

324 dtype='timedelta64[ns]', freq='D') 

325 

326 The ``freq`` parameter specifies the frequency of the TimedeltaIndex. 

327 Only fixed frequencies can be passed, non-fixed frequencies such as 

328 'M' (month end) will raise. 

329 

330 >>> pd.timedelta_range(start='1 day', end='2 days', freq='6h') 

331 TimedeltaIndex(['1 days 00:00:00', '1 days 06:00:00', '1 days 12:00:00', 

332 '1 days 18:00:00', '2 days 00:00:00'], 

333 dtype='timedelta64[ns]', freq='6h') 

334 

335 Specify ``start``, ``end``, and ``periods``; the frequency is generated 

336 automatically (linearly spaced). 

337 

338 >>> pd.timedelta_range(start='1 day', end='5 days', periods=4) 

339 TimedeltaIndex(['1 days 00:00:00', '2 days 08:00:00', '3 days 16:00:00', 

340 '5 days 00:00:00'], 

341 dtype='timedelta64[ns]', freq=None) 

342 

343 **Specify a unit** 

344 

345 >>> pd.timedelta_range("1 Day", periods=3, freq="100000D", unit="s") 

346 TimedeltaIndex(['1 days', '100001 days', '200001 days'], 

347 dtype='timedelta64[s]', freq='100000D') 

348 """ 

349 if freq is None and com.any_none(periods, start, end): 

350 freq = "D" 

351 

352 freq = to_offset(freq) 

353 tdarr = TimedeltaArray._generate_range( 

354 start, end, periods, freq, closed=closed, unit=unit 

355 ) 

356 return TimedeltaIndex._simple_new(tdarr, name=name)