test_timedeltas.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. # -*- coding: utf-8 -*-
  2. import numpy as np
  3. import pytest
  4. import pandas as pd
  5. from pandas.core.arrays import TimedeltaArray
  6. import pandas.util.testing as tm
  7. class TestTimedeltaArrayConstructor(object):
  8. def test_only_1dim_accepted(self):
  9. # GH#25282
  10. arr = np.array([0, 1, 2, 3], dtype='m8[h]').astype('m8[ns]')
  11. with pytest.raises(ValueError, match="Only 1-dimensional"):
  12. # 2-dim
  13. TimedeltaArray(arr.reshape(2, 2))
  14. with pytest.raises(ValueError, match="Only 1-dimensional"):
  15. # 0-dim
  16. TimedeltaArray(arr[[0]].squeeze())
  17. def test_freq_validation(self):
  18. # ensure that the public constructor cannot create an invalid instance
  19. arr = np.array([0, 0, 1], dtype=np.int64) * 3600 * 10**9
  20. msg = ("Inferred frequency None from passed values does not "
  21. "conform to passed frequency D")
  22. with pytest.raises(ValueError, match=msg):
  23. TimedeltaArray(arr.view('timedelta64[ns]'), freq="D")
  24. def test_non_array_raises(self):
  25. with pytest.raises(ValueError, match='list'):
  26. TimedeltaArray([1, 2, 3])
  27. def test_other_type_raises(self):
  28. with pytest.raises(ValueError,
  29. match="dtype bool cannot be converted"):
  30. TimedeltaArray(np.array([1, 2, 3], dtype='bool'))
  31. def test_incorrect_dtype_raises(self):
  32. # TODO: why TypeError for 'category' but ValueError for i8?
  33. with pytest.raises(ValueError,
  34. match=r'category cannot be converted '
  35. r'to timedelta64\[ns\]'):
  36. TimedeltaArray(np.array([1, 2, 3], dtype='i8'), dtype='category')
  37. with pytest.raises(ValueError,
  38. match=r"dtype int64 cannot be converted "
  39. r"to timedelta64\[ns\]"):
  40. TimedeltaArray(np.array([1, 2, 3], dtype='i8'),
  41. dtype=np.dtype("int64"))
  42. def test_copy(self):
  43. data = np.array([1, 2, 3], dtype='m8[ns]')
  44. arr = TimedeltaArray(data, copy=False)
  45. assert arr._data is data
  46. arr = TimedeltaArray(data, copy=True)
  47. assert arr._data is not data
  48. assert arr._data.base is not data
  49. class TestTimedeltaArray(object):
  50. def test_np_sum(self):
  51. # GH#25282
  52. vals = np.arange(5, dtype=np.int64).view('m8[h]').astype('m8[ns]')
  53. arr = TimedeltaArray(vals)
  54. result = np.sum(arr)
  55. assert result == vals.sum()
  56. result = np.sum(pd.TimedeltaIndex(arr))
  57. assert result == vals.sum()
  58. def test_from_sequence_dtype(self):
  59. msg = "dtype .*object.* cannot be converted to timedelta64"
  60. with pytest.raises(ValueError, match=msg):
  61. TimedeltaArray._from_sequence([], dtype=object)
  62. def test_abs(self):
  63. vals = np.array([-3600 * 10**9, 'NaT', 7200 * 10**9], dtype='m8[ns]')
  64. arr = TimedeltaArray(vals)
  65. evals = np.array([3600 * 10**9, 'NaT', 7200 * 10**9], dtype='m8[ns]')
  66. expected = TimedeltaArray(evals)
  67. result = abs(arr)
  68. tm.assert_timedelta_array_equal(result, expected)
  69. def test_neg(self):
  70. vals = np.array([-3600 * 10**9, 'NaT', 7200 * 10**9], dtype='m8[ns]')
  71. arr = TimedeltaArray(vals)
  72. evals = np.array([3600 * 10**9, 'NaT', -7200 * 10**9], dtype='m8[ns]')
  73. expected = TimedeltaArray(evals)
  74. result = -arr
  75. tm.assert_timedelta_array_equal(result, expected)
  76. def test_neg_freq(self):
  77. tdi = pd.timedelta_range('2 Days', periods=4, freq='H')
  78. arr = TimedeltaArray(tdi, freq=tdi.freq)
  79. expected = TimedeltaArray(-tdi._data, freq=-tdi.freq)
  80. result = -arr
  81. tm.assert_timedelta_array_equal(result, expected)
  82. @pytest.mark.parametrize("dtype", [
  83. int, np.int32, np.int64, 'uint32', 'uint64',
  84. ])
  85. def test_astype_int(self, dtype):
  86. arr = TimedeltaArray._from_sequence([pd.Timedelta('1H'),
  87. pd.Timedelta('2H')])
  88. result = arr.astype(dtype)
  89. if np.dtype(dtype).kind == 'u':
  90. expected_dtype = np.dtype('uint64')
  91. else:
  92. expected_dtype = np.dtype('int64')
  93. expected = arr.astype(expected_dtype)
  94. assert result.dtype == expected_dtype
  95. tm.assert_numpy_array_equal(result, expected)
  96. def test_setitem_clears_freq(self):
  97. a = TimedeltaArray(pd.timedelta_range('1H', periods=2, freq='H'))
  98. a[0] = pd.Timedelta("1H")
  99. assert a.freq is None
  100. class TestReductions(object):
  101. def test_min_max(self):
  102. arr = TimedeltaArray._from_sequence([
  103. '3H', '3H', 'NaT', '2H', '5H', '4H',
  104. ])
  105. result = arr.min()
  106. expected = pd.Timedelta('2H')
  107. assert result == expected
  108. result = arr.max()
  109. expected = pd.Timedelta('5H')
  110. assert result == expected
  111. result = arr.min(skipna=False)
  112. assert result is pd.NaT
  113. result = arr.max(skipna=False)
  114. assert result is pd.NaT
  115. @pytest.mark.parametrize('skipna', [True, False])
  116. def test_min_max_empty(self, skipna):
  117. arr = TimedeltaArray._from_sequence([])
  118. result = arr.min(skipna=skipna)
  119. assert result is pd.NaT
  120. result = arr.max(skipna=skipna)
  121. assert result is pd.NaT