Ejemplo n.º 1
0
    def test__to_text__without_metadata(self):
        path = self.target_dir + "/to_text_without_metadata"
        my_time_series = TimeSeries(self.my_series)
        my_time_series.to_text(path)

        data_csv_path = "{}/{}.{}".format(path, TIME_SERIES_FILENAME,
                                          TIME_SERIES_EXT)
        does_data_csv_exist = os_path.exists(data_csv_path)
        self.assertTrue(does_data_csv_exist)

        meta_json_path = "{}/{}.{}".format(path, METADATA_FILENAME,
                                           METADATA_EXT)
        does_meta_json_exist = os_path.exists(meta_json_path)
        self.assertFalse(does_meta_json_exist)
Ejemplo n.º 2
0
class TestTimeSeries(TestCase):
    def setUp(self) -> None:

        # Create a time indexed series
        index = DatetimeIndex(
            ['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04'])
        self.my_series = Series([0.4, 1.0, 0.7, 0.6], index=index)

        # Create metadata
        my_unit = {"name": "power", "symbol": "W", "data_type": "float"}
        my_coordinates = {"lat": 46.796611, "lon": 7.147563}
        my_dict = {"unit": my_unit, "coordinates": my_coordinates}
        self.my_metadata = Metadata(my_dict)

        self.my_time_series = TimeSeries(self.my_series, self.my_metadata)

        # Define a target directory
        self.target_dir = "data/test-export"

    def test__init__is_instance(self):
        self.my_time_series = TimeSeries()
        self.assertIsInstance(self.my_time_series, TimeSeries,
                              "The TimeSeries hasn't the right type")

    def test__init__has_right_types(self):
        # Add some data
        index = DatetimeIndex(
            ['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04'])
        my_series = DataFrame([0.4, 1.0, 0.7, 0.6], index=index)
        my_metadata = Metadata()
        my_ts = TimeSeries(my_series, my_metadata)
        # Check types
        self.assertIsInstance(
            my_ts.series, DataFrame,
            "The TimeSeries series is not a Pandas DataFrame")
        self.assertIsInstance(
            my_ts.metadata, Metadata,
            "The TimeSeries Metadata hasn't got the right type")

    def test__init__contains_metadata(self):
        # Add some data
        index = DatetimeIndex(
            ['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04'])
        my_series = DataFrame([0.4, 1.0, 0.7, 0.6], index=index)
        my_metadata = Metadata()
        my_ts = TimeSeries(my_series, my_metadata)
        # Check types
        self.assertNotEqual(my_ts.metadata, None,
                            "The TimeSeries Metadata is probably None")

    def test__init__has_values_as_column_name(self):
        index = DatetimeIndex(
            ['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04'])
        my_series = Series([0.4, 1.0, 0.7, 0.6], index=index)
        ts = TimeSeries(my_series)
        self.assertTrue(TIME_SERIES_VALUES in ts.series.columns)

    def test__init__wrong_index_type(self):
        values = Series([0.4, 1.0, 0.7, 0.6])
        with self.assertRaises(AssertionError):
            TimeSeries(values)

    def test__init__with_Series_input(self):
        index = DatetimeIndex(
            ['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04'])
        my_series = Series([0.4, 1.0, 0.7, 0.6], index=index)
        ts = TimeSeries(my_series)
        self.assertTrue(TIME_SERIES_VALUES in ts.series.columns)
        self.assertIsInstance(ts, TimeSeries)

    def test__init__with_DataFrame_input_single_column(self):
        index = DatetimeIndex(
            ['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04'])
        my_series = Series([0.4, 1.0, 0.7, 0.6], index=index)
        df = DataFrame(data=my_series)
        ts = TimeSeries(df)
        self.assertTrue(TIME_SERIES_VALUES in ts.series.columns)
        self.assertIsInstance(ts, TimeSeries)

    def test__init__with_DataFrame_input_many_columns__without_values(self):
        index = DatetimeIndex(
            ['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04'])
        my_series = Series([0.4, 1.0, 0.7, 0.6], index=index)
        df = DataFrame({"one": my_series, "two": my_series})
        with self.assertRaises(AssertionError):
            ts = TimeSeries(df)

    def test__init__with_DataFrame_input_many_columns__with_values(self):
        index = DatetimeIndex(
            ['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04'])
        my_series = Series([0.4, 1.0, 0.7, 0.6], index=index)
        df = DataFrame({TIME_SERIES_VALUES: my_series, "two": my_series})
        ts = TimeSeries(df)
        self.assertIsInstance(ts, TimeSeries)

    def test__init__freq_is_infered(self):
        index = DatetimeIndex(
            ['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04'])
        my_series = Series([0.4, 1.0, 0.7, 0.6], index=index)
        ts = TimeSeries(my_series)
        self.assertEqual(infer_freq(index), ts.series.index.freq)

    def test__create(self):
        ts = TimeSeries.create("01-01-2020", "02-01-2020")
        self.assertIsInstance(ts, TimeSeries)
        # Test if all elements are NaNs
        self.assertTrue(ts.series.isna().all().values[0])
        # Test if frequency is daily
        self.assertEqual(ts.series.index.inferred_freq, 'D')

    def test__create__is_regular(self):
        ts = TimeSeries.create("01-01-2020", "02-01-2020")
        no_duration_diff = ts.index.to_series().diff().diff()[2:] == \
                           Timedelta(0)
        is_regular = no_duration_diff.eq(True).all()
        self.assertTrue(is_regular)

    def test__create__with_freq_as_str(self):
        ts = TimeSeries.create("01-01-2020", "02-01-2020", "H")
        self.assertIsInstance(ts, TimeSeries)
        # Test if all elements are NaNs
        self.assertTrue(ts.series.isna().all().values[0])
        # Test if frequency is daily
        self.assertEqual(ts.series.index.inferred_freq, 'H')

    def test__create__with_freq_as_time_series(self):
        ts_freq = TimeSeries.create("01-01-2020", "02-01-2020", "H")
        ts = TimeSeries.create("01-01-2020", "02-01-2020", ts_freq)
        self.assertIsInstance(ts, TimeSeries)
        # Test if all elements are NaNs
        self.assertTrue(ts.series.isna().all().values[0])
        # Test if frequency is daily
        self.assertEqual(ts.series.index.inferred_freq,
                         ts_freq.series.index.inferred_freq)

    def test__plot__returns_graph_object_axes(self):
        ts = TimeSeries.create("01-01-2020", "02-01-2020", "H")
        my_fig = ts.plot()
        self.assertIsInstance(my_fig, Axes)

    def test__plot__returns_graph_object_plotly(self):
        ts = TimeSeries.create("01-01-2020", "02-01-2020", "H")
        my_fig = ts.plot(context="notebook")
        self.assertIsInstance(my_fig, Figure)

    def test__copy__shallow(self):
        # object creation
        ts = TimeSeries.create("01-2020", "03-2020", "H")
        copy = ts.copy(deep=False)
        self.assertNotEqual(id(ts), id(copy))

    def test__copy__deep(self):
        # object creation
        ts = TimeSeries.create("01-2020", "03-2020", "H")
        copy = ts.copy(deep=True)
        self.assertNotEqual(id(ts), id(copy))

    def test__split_at(self):
        # Create TimeSeries and split it
        ts = TimeSeries.create("01-01-2020", "03-01-2020", "H")
        a, b = ts.split_at("02-01-2020 00:00")
        # Get all the indexes
        ts_start = ts.series[TIME_SERIES_VALUES].index[0]
        ts_end = ts.series[TIME_SERIES_VALUES].index[-1]
        a_start = a.series[TIME_SERIES_VALUES].index[0]
        a_end = a.series[TIME_SERIES_VALUES].index[-1]
        b_start = b.series[TIME_SERIES_VALUES].index[0]
        b_end = b.series[TIME_SERIES_VALUES].index[-1]
        # Test boundaries
        self.assertEqual(ts_start, a_start)
        self.assertEqual(ts_end, b_end)
        # Test split point
        self.assertEqual(a_end, b_start)

    def test__split_in_chunks(self):
        ts = TimeSeries.create("01-01-2020", "03-01-2020", "H")
        chunk_len = 5
        # method at test
        chunks = ts.split_in_chunks(chunk_len)
        # test all element but last
        for ts_chunk in chunks[:-1]:
            self.assertEqual(len(ts_chunk), chunk_len)
        # test last element
        self.assertLessEqual(len(chunks[-1]), chunk_len)

    def test__fill(self):
        ts = TimeSeries.create("01-01-2020", "03-01-2020", "H")
        val = 42
        # method at test
        ts = ts.fill(val)
        # test
        for i in ts:
            self.assertEqual(val, i)

    def test__empty(self):
        ts = TimeSeries.create("01-01-2020", "03-01-2020", "H")
        # method at test
        ts = ts.empty()
        # test
        for i in ts:
            self.assertTrue(np.isnan(i))

    def test__pad(self):
        def is_regular(ts):
            # test if double timestamps in ts
            no_duration_diff = ts.index.to_series().diff().diff()[2:] == \
                               Timedelta(0)
            return no_duration_diff.eq(True).all()

        def is_monotonic(ts):
            # test if monotonic
            return ts.series.index.is_monotonic

        def is_freq_similar(ts_before, ts_after):
            # test if freq is the same
            return ts_before.frequency() == ts_after.frequency()

        # Create TimeSeries
        ts_1 = TimeSeries.create("04-2020", "05-2020", "D")

        # Pad before
        ts_1_padded_before = ts_1.pad("03-2020")["2020-03-31":"2020-04-02"]
        self.assertTrue(is_regular(ts_1_padded_before))
        self.assertTrue(is_monotonic(ts_1_padded_before))
        self.assertTrue(is_freq_similar(ts_1, ts_1_padded_before))

        # Pad after
        ts_1_padded_after = ts_1.pad("06-2020")["2020-05-29":"2020-06-02"]
        self.assertTrue(is_regular(ts_1_padded_after))
        self.assertTrue(is_monotonic(ts_1_padded_after))
        self.assertTrue(is_freq_similar(ts_1, ts_1_padded_after))

        # Pad during (wrong case)
        with self.assertRaises(ValueError):
            ts_1.pad("2020-04-15")

    def test__trim__both_side_by_default(self):
        # Prepare TimeSeries with int as values
        start = Timestamp("01-01-2020")
        end = Timestamp("03-01-2020")
        ts_initial = TimeSeries.create(start, end, "H")
        ts_initial = ts_initial.fill(42)
        # Pad the TimeSeries with np.nans
        ts_pad = ts_initial.pad("01-12-2019").pad("05-01-2020")
        # Method at test
        ts_trimmed = ts_pad.trim()
        # test if no NaNs
        self.assertFalse(ts_trimmed.series.isna().values.any())
        # test boundaries
        new_start, new_end = ts_trimmed.boundaries()
        self.assertEqual(start, new_start)
        self.assertEqual(end, new_end)

    def test__trim__only_start(self):
        # Prepare TimeSeries with int as values
        start = Timestamp("01-01-2020")
        end = Timestamp("03-01-2020")
        ts_initial = TimeSeries.create(start, end, "H")
        ts_initial = ts_initial.fill(42)
        # Pad the TimeSeries with np.nans
        pad_start = Timestamp("01-12-2019")
        pad_end = Timestamp("05-01-2020")
        ts_pad = ts_initial.pad(pad_start).pad(pad_end)
        # Method at test
        ts_trimmed = ts_pad.trim(side="start")
        # test if NaNs
        self.assertTrue(ts_trimmed.series.isna().values.any())
        # test boundaries
        new_start, new_end = ts_trimmed.boundaries()
        self.assertEqual(start, new_start)
        self.assertEqual(pad_end, new_end)

    def test__trim__only_end(self):
        # Prepare TimeSeries with int as values
        start = Timestamp("01-01-2020")
        end = Timestamp("03-01-2020")
        ts_initial = TimeSeries.create(start, end, "H")
        ts_initial = ts_initial.fill(42)
        # Pad the TimeSeries with np.nans
        pad_start = Timestamp("01-12-2019")
        pad_end = Timestamp("05-01-2020")
        ts_pad = ts_initial.pad(pad_start).pad(pad_end)
        # Method at test
        ts_trimmed = ts_pad.trim(side="end")
        # test if NaNs
        self.assertTrue(ts_trimmed.series.isna().values.any())
        # test boundaries
        new_start, new_end = ts_trimmed.boundaries()
        self.assertEqual(pad_start, new_start)
        self.assertEqual(end, new_end)

    def test__merge(self):
        # Prepare test
        ts1 = TimeSeries.create("01-2020", "03-2020", "H")
        ts2 = TimeSeries.create("02-2020", "04-2020", "H")
        # Call function
        ts = ts1.merge(ts2)
        # Test if index is monotonic increasing
        self.assertTrue(ts.series.index.is_monotonic_increasing)
        # Test if all values are there
        len1 = len(ts1) + len(ts2)
        len2 = len(ts)
        self.assertTrue(len1 == len2)

    def test__apply__on_self(self):
        # Prepare test
        val = 21
        ts = TimeSeries.create("01-2020", "02-2020", "H").fill(val)
        # Method at test
        ts = ts.apply(lambda x: x * 2)
        # Test
        for i in ts:
            self.assertEqual(i, val * 2)

    def test__apply__on_other_time_series(self):
        # Prepare test
        val_1 = 21
        val_2 = 3
        ts_1 = TimeSeries.create("01-2020", "02-2020", "H").fill(val_1)
        ts_2 = TimeSeries.create("01-2020", "02-2020", "H").fill(val_2)
        # Method at test
        ts = ts_1.apply(lambda x, y: x * y, ts_2)
        # Test
        for i in ts:
            self.assertEqual(i, val_1 * val_2)

    def test__apply__on_other_time_series_with_different_length(self):
        # Prepare test
        val_1 = 21
        val_2 = 3
        ts_1 = TimeSeries.create("01-2020", "02-2020", "H").fill(val_1)
        ts_2 = TimeSeries.create("01-2020", "04-2020", "H").fill(val_2)
        # Method at test
        with self.assertRaises(AssertionError):
            ts = ts_1.apply(lambda x, y: x * y, ts_2)

    def test__time_deltas(self):
        ts = TimeSeries.create("01-2020", "03-2020", "H")
        deltas = ts.time_detlas()
        for i in deltas[1:]:
            self.assertEqual(i, 3600.0)
            self.assertIs(type(i), float)

    def test__to_text__without_metadata(self):
        path = self.target_dir + "/to_text_without_metadata"
        my_time_series = TimeSeries(self.my_series)
        my_time_series.to_text(path)

        data_csv_path = "{}/{}.{}".format(path, TIME_SERIES_FILENAME,
                                          TIME_SERIES_EXT)
        does_data_csv_exist = os_path.exists(data_csv_path)
        self.assertTrue(does_data_csv_exist)

        meta_json_path = "{}/{}.{}".format(path, METADATA_FILENAME,
                                           METADATA_EXT)
        does_meta_json_exist = os_path.exists(meta_json_path)
        self.assertFalse(does_meta_json_exist)

    def test__to_text__with_metadata(self):
        path = self.target_dir + "/to_text_with_metadata"
        self.my_time_series.to_text(path)

        data_csv_path = "{}/{}.{}".format(path, TIME_SERIES_FILENAME,
                                          TIME_SERIES_EXT)
        does_data_csv_exist = os_path.exists(data_csv_path)
        self.assertTrue(does_data_csv_exist)

        meta_json_path = "{}/{}.{}".format(path, METADATA_FILENAME,
                                           METADATA_EXT)
        does_meta_json_exist = os_path.exists(meta_json_path)
        self.assertTrue(does_meta_json_exist)

    def test__to_pickle(self):
        pickle_path = "{}/{}.{}".format(self.target_dir,
                                        DEFAULT_EXPORT_FILENAME, PICKLE_EXT)
        self.my_time_series.to_pickle(pickle_path)
        does_pickle_exist = os_path.exists(pickle_path)
        self.assertTrue(does_pickle_exist)

    def test__to_df(self):
        df = self.my_time_series.to_df()
        self.assertTrue(df['values'].equals(self.my_series))
        self.assertIsInstance(df, DataFrame)

    def test__to_darts__type_check(self):
        ts = TimeSeries.create("01-2020", "02-2020", "H")
        ts = ts.fill(np.random.randint(0, 1000, len(ts)))
        self.assertIsInstance(ts, TimeSeries)
        dts = ts.to_darts()
        from darts import TimeSeries as DartsTimeSeries
        self.assertIsInstance(dts, DartsTimeSeries)

    def test__to_darts__series_equality(self):
        ts = TimeSeries.create("01-2020", "02-2020", "H")
        ts = ts.fill(np.random.randint(0, 1000, len(ts)))
        dts = ts.to_darts()
        is_equal = ts.series[TIME_SERIES_VALUES].equals(dts.pd_series())
        self.assertTrue(is_equal)

    def tearDown(self) -> None:
        del self.my_time_series
        shutil.rmtree(self.target_dir, ignore_errors=True)