diff --git a/src/urban_meal_delivery/forecasts/timify.py b/src/urban_meal_delivery/forecasts/timify.py index c52aef3..48d1732 100644 --- a/src/urban_meal_delivery/forecasts/timify.py +++ b/src/urban_meal_delivery/forecasts/timify.py @@ -53,7 +53,7 @@ class OrderHistory: Returns: order_totals: a one-column `DataFrame` with a `MultiIndex` of the "pixel_id"s and "start_at"s (i.e., beginnings of the intervals); - the column with data is "total_orders" + the column with data is "n_orders" """ if self._data is None: self._data = self.aggregate_orders() @@ -69,7 +69,7 @@ class OrderHistory: SELECT pixel_id, start_at, - COUNT(*) AS total_orders + COUNT(*) AS n_orders FROM ( SELECT pixel_id, @@ -152,7 +152,7 @@ class OrderHistory: return data.reindex(index, fill_value=0) - def make_horizontal_time_series( # noqa:WPS210 + def make_horizontal_ts( # noqa:WPS210 self, pixel_id: int, predict_at: dt.datetime, train_horizon: int, ) -> Tuple[pd.Series, int, pd.Series]: """Slice a horizontal time series out of the `.totals`. @@ -209,19 +209,19 @@ class OrderHistory: # Take only the counts at the `predict_at` time. training_ts = intra_pixel.loc[ - first_start_at : last_start_at : self._n_daily_time_steps, # type: ignore - 'total_orders', + first_start_at : last_start_at : self._n_daily_time_steps, # type:ignore + 'n_orders', ] if len(training_ts) != frequency * train_horizon: raise RuntimeError('Not enough historic data for `predict_at`') - actuals_ts = intra_pixel.loc[[predict_at], 'total_orders'] + actuals_ts = intra_pixel.loc[[predict_at], 'n_orders'] if not len(actuals_ts): # pragma: no cover raise LookupError('`predict_at` is not in the order history') return training_ts, frequency, actuals_ts - def make_vertical_time_series( # noqa:WPS210 + def make_vertical_ts( # noqa:WPS210 self, pixel_id: int, predict_day: dt.date, train_horizon: int, ) -> Tuple[pd.Series, int, pd.Series]: """Slice a vertical time series out of the `.totals`. @@ -277,8 +277,8 @@ class OrderHistory: # Take all the counts between `first_train_day` and `last_train_day`. training_ts = intra_pixel.loc[ - first_start_at:last_start_at, # type: ignore - 'total_orders', + first_start_at:last_start_at, # type:ignore + 'n_orders', ] if len(training_ts) != frequency * train_horizon: raise RuntimeError('Not enough historic data for `predict_day`') @@ -299,15 +299,15 @@ class OrderHistory: ) - dt.timedelta(minutes=self._time_step) actuals_ts = intra_pixel.loc[ - first_prediction_at:last_prediction_at, # type: ignore - 'total_orders', + first_prediction_at:last_prediction_at, # type:ignore + 'n_orders', ] if not len(actuals_ts): # pragma: no cover raise LookupError('`predict_day` is not in the order history') return training_ts, frequency, actuals_ts - def make_real_time_time_series( # noqa:WPS210 + def make_realtime_ts( # noqa:WPS210 self, pixel_id: int, predict_at: dt.datetime, train_horizon: int, ) -> Tuple[pd.Series, int, pd.Series]: """Slice a vertical real-time time series out of the `.totals`. @@ -374,8 +374,8 @@ class OrderHistory: # Take all the counts between `first_train_day` and `last_train_day`, # including the ones on the `predict_at` day prior to `predict_at`. training_ts = intra_pixel.loc[ - first_start_at:last_start_at, # type: ignore - 'total_orders', + first_start_at:last_start_at, # type:ignore + 'n_orders', ] n_time_steps_on_predict_day = ( ( @@ -394,7 +394,7 @@ class OrderHistory: if len(training_ts) != frequency * train_horizon + n_time_steps_on_predict_day: raise RuntimeError('Not enough historic data for `predict_day`') - actuals_ts = intra_pixel.loc[[predict_at], 'total_orders'] + actuals_ts = intra_pixel.loc[[predict_at], 'n_orders'] if not len(actuals_ts): # pragma: no cover raise LookupError('`predict_at` is not in the order history') diff --git a/tests/forecasts/conftest.py b/tests/forecasts/conftest.py index 08c2439..c7fcf3b 100644 --- a/tests/forecasts/conftest.py +++ b/tests/forecasts/conftest.py @@ -42,8 +42,8 @@ def horizontal_datetime_index(): @pytest.fixture def horizontal_no_demand(horizontal_datetime_index): - """A horizontal time series of order totals when there was no demand.""" - return pd.Series(0, index=horizontal_datetime_index, name='order_totals') + """A horizontal time series with order totals: no demand.""" + return pd.Series(0, index=horizontal_datetime_index, name='n_orders') @pytest.fixture @@ -72,5 +72,5 @@ def vertical_datetime_index(): @pytest.fixture def vertical_no_demand(vertical_datetime_index): - """A vertical time series of order totals when there was no demand.""" - return pd.Series(0, index=vertical_datetime_index, name='order_totals') + """A vertical time series with order totals: no demand.""" + return pd.Series(0, index=vertical_datetime_index, name='n_orders') diff --git a/tests/forecasts/timify/test_aggregate_orders.py b/tests/forecasts/timify/test_aggregate_orders.py index 75f0531..325db74 100644 --- a/tests/forecasts/timify/test_aggregate_orders.py +++ b/tests/forecasts/timify/test_aggregate_orders.py @@ -91,9 +91,9 @@ class TestAggregateOrders: # The resulting `DataFrame` has 12 rows holding `1`s. assert len(result) == 12 - assert result['total_orders'].min() == 1 - assert result['total_orders'].max() == 1 - assert result['total_orders'].sum() == 12 + assert result['n_orders'].min() == 1 + assert result['n_orders'].max() == 1 + assert result['n_orders'].sum() == 12 def test_evenly_distributed_ad_hoc_orders_with_no_demand_late( # noqa:WPS218 self, db_session, one_pixel_grid, restaurant, make_order, @@ -123,10 +123,10 @@ class TestAggregateOrders: # Even though there are only 10 orders, there are 12 rows in the `DataFrame`. # That is so as `0`s are filled in for hours without any demand at the end. assert len(result) == 12 - assert result['total_orders'].min() == 0 - assert result['total_orders'].max() == 1 - assert result.iloc[:10]['total_orders'].sum() == 10 - assert result.iloc[10:]['total_orders'].sum() == 0 + assert result['n_orders'].min() == 0 + assert result['n_orders'].max() == 1 + assert result.iloc[:10]['n_orders'].sum() == 10 + assert result.iloc[10:]['n_orders'].sum() == 0 def test_one_ad_hoc_order_every_other_hour( self, db_session, one_pixel_grid, restaurant, make_order, @@ -155,9 +155,9 @@ class TestAggregateOrders: # The resulting `DataFrame` has 12 rows, 6 holding `0`s, and 6 holding `1`s. assert len(result) == 12 - assert result['total_orders'].min() == 0 - assert result['total_orders'].max() == 1 - assert result['total_orders'].sum() == 6 + assert result['n_orders'].min() == 0 + assert result['n_orders'].max() == 1 + assert result['n_orders'].sum() == 6 def test_one_ad_hoc_and_one_pre_order( self, db_session, one_pixel_grid, restaurant, make_order, @@ -199,9 +199,9 @@ class TestAggregateOrders: # The resulting `DataFrame` has 12 rows, 11 holding `0`s, and one holding a `1`. assert len(result) == 12 - assert result['total_orders'].min() == 0 - assert result['total_orders'].max() == 1 - assert result['total_orders'].sum() == 1 + assert result['n_orders'].min() == 0 + assert result['n_orders'].max() == 1 + assert result['n_orders'].sum() == 1 def test_evenly_distributed_ad_hoc_orders_with_half_hour_time_steps( # noqa:WPS218 self, db_session, one_pixel_grid, restaurant, make_order, @@ -234,10 +234,10 @@ class TestAggregateOrders: # The resulting `DataFrame` has 24 rows for the 24 30-minute time steps. # The rows' values are `0` and `1` alternating. assert len(result) == 24 - assert result['total_orders'].min() == 0 - assert result['total_orders'].max() == 1 - assert result.iloc[::2]['total_orders'].sum() == 12 - assert result.iloc[1::2]['total_orders'].sum() == 0 + assert result['n_orders'].min() == 0 + assert result['n_orders'].max() == 1 + assert result.iloc[::2]['n_orders'].sum() == 12 + assert result.iloc[1::2]['n_orders'].sum() == 0 def test_ad_hoc_orders_over_two_days( self, db_session, one_pixel_grid, restaurant, make_order, @@ -285,9 +285,9 @@ class TestAggregateOrders: # The resulting `DataFrame` has 24 rows, 12 for each day. assert len(result) == 24 - assert result['total_orders'].min() == 0 - assert result['total_orders'].max() == 1 - assert result['total_orders'].sum() == 18 + assert result['n_orders'].min() == 0 + assert result['n_orders'].max() == 1 + assert result['n_orders'].sum() == 18 @pytest.fixture def two_pixel_grid( # noqa:WPS211 @@ -381,6 +381,6 @@ class TestAggregateOrders: # The resulting `DataFrame` has 24 rows, 12 for each pixel. assert len(result) == 24 - assert result['total_orders'].min() == 0 - assert result['total_orders'].max() == 2 - assert result['total_orders'].sum() == 30 + assert result['n_orders'].min() == 0 + assert result['n_orders'].max() == 2 + assert result['n_orders'].sum() == 30 diff --git a/tests/forecasts/timify/test_make_time_series.py b/tests/forecasts/timify/test_make_time_series.py index 4dc187d..d828a9a 100644 --- a/tests/forecasts/timify/test_make_time_series.py +++ b/tests/forecasts/timify/test_make_time_series.py @@ -41,7 +41,7 @@ def order_totals(good_pixel_id): index = pd.MultiIndex.from_tuples(gen) index.names = ['pixel_id', 'start_at'] - df = pd.DataFrame(data={'total_orders': 0}, index=index) + df = pd.DataFrame(data={'n_orders': 0}, index=index) # Sanity check: n_pixels * n_time_steps_per_day * n_weekdays * n_weeks. assert len(df) == 2 * 12 * (7 * 2 + 1) @@ -88,13 +88,13 @@ def bad_predict_at(): class TestMakeHorizontalTimeSeries: - """Test the `OrderHistory.make_horizontal_time_series()` method.""" + """Test the `OrderHistory.make_horizontal_ts()` method.""" @pytest.mark.parametrize('train_horizon', test_config.TRAIN_HORIZONS) def test_wrong_pixel(self, order_history, good_predict_at, train_horizon): """A `pixel_id` that is not in the `grid`.""" with pytest.raises(LookupError): - order_history.make_horizontal_time_series( + order_history.make_horizontal_ts( pixel_id=999_999, predict_at=good_predict_at, train_horizon=train_horizon, @@ -105,7 +105,7 @@ class TestMakeHorizontalTimeSeries: self, order_history, good_pixel_id, good_predict_at, train_horizon, ): """The time series come as a `pd.Series`.""" - result = order_history.make_horizontal_time_series( + result = order_history.make_horizontal_ts( pixel_id=good_pixel_id, predict_at=good_predict_at, train_horizon=train_horizon, @@ -114,9 +114,9 @@ class TestMakeHorizontalTimeSeries: training_ts, _, actuals_ts = result assert isinstance(training_ts, pd.Series) - assert training_ts.name == 'total_orders' + assert training_ts.name == 'n_orders' assert isinstance(actuals_ts, pd.Series) - assert actuals_ts.name == 'total_orders' + assert actuals_ts.name == 'n_orders' @pytest.mark.parametrize('train_horizon', test_config.TRAIN_HORIZONS) def test_time_series_have_correct_length( @@ -126,7 +126,7 @@ class TestMakeHorizontalTimeSeries: ... whereas the time series with the actual order counts has only `1` value. """ - result = order_history.make_horizontal_time_series( + result = order_history.make_horizontal_ts( pixel_id=good_pixel_id, predict_at=good_predict_at, train_horizon=train_horizon, @@ -142,7 +142,7 @@ class TestMakeHorizontalTimeSeries: self, order_history, good_pixel_id, good_predict_at, train_horizon, ): """The `frequency` must be `7`.""" - result = order_history.make_horizontal_time_series( + result = order_history.make_horizontal_ts( pixel_id=good_pixel_id, predict_at=good_predict_at, train_horizon=train_horizon, @@ -161,7 +161,7 @@ class TestMakeHorizontalTimeSeries: ... the history of order totals is not long enough. """ with pytest.raises(RuntimeError): - order_history.make_horizontal_time_series( + order_history.make_horizontal_ts( pixel_id=good_pixel_id, predict_at=bad_predict_at, train_horizon=train_horizon, @@ -175,19 +175,19 @@ class TestMakeHorizontalTimeSeries: ... the history of order totals can never be long enough. """ with pytest.raises(RuntimeError): - order_history.make_horizontal_time_series( + order_history.make_horizontal_ts( pixel_id=good_pixel_id, predict_at=good_predict_at, train_horizon=999, ) class TestMakeVerticalTimeSeries: - """Test the `OrderHistory.make_vertical_time_series()` method.""" + """Test the `OrderHistory.make_vertical_ts()` method.""" @pytest.mark.parametrize('train_horizon', test_config.TRAIN_HORIZONS) def test_wrong_pixel(self, order_history, good_predict_at, train_horizon): """A `pixel_id` that is not in the `grid`.""" with pytest.raises(LookupError): - order_history.make_vertical_time_series( + order_history.make_vertical_ts( pixel_id=999_999, predict_day=good_predict_at.date(), train_horizon=train_horizon, @@ -198,7 +198,7 @@ class TestMakeVerticalTimeSeries: self, order_history, good_pixel_id, good_predict_at, train_horizon, ): """The time series come as `pd.Series`.""" - result = order_history.make_vertical_time_series( + result = order_history.make_vertical_ts( pixel_id=good_pixel_id, predict_day=good_predict_at.date(), train_horizon=train_horizon, @@ -207,9 +207,9 @@ class TestMakeVerticalTimeSeries: training_ts, _, actuals_ts = result assert isinstance(training_ts, pd.Series) - assert training_ts.name == 'total_orders' + assert training_ts.name == 'n_orders' assert isinstance(actuals_ts, pd.Series) - assert actuals_ts.name == 'total_orders' + assert actuals_ts.name == 'n_orders' @pytest.mark.parametrize('train_horizon', test_config.TRAIN_HORIZONS) def test_time_series_have_correct_length( @@ -223,7 +223,7 @@ class TestMakeVerticalTimeSeries: The time series with the actual order counts always holds one observation per time step of a day. """ - result = order_history.make_vertical_time_series( + result = order_history.make_vertical_ts( pixel_id=good_pixel_id, predict_day=good_predict_at.date(), train_horizon=train_horizon, @@ -245,7 +245,7 @@ class TestMakeVerticalTimeSeries: self, order_history, good_pixel_id, good_predict_at, train_horizon, ): """The `frequency` is the number of weekly time steps.""" - result = order_history.make_vertical_time_series( + result = order_history.make_vertical_ts( pixel_id=good_pixel_id, predict_day=good_predict_at.date(), train_horizon=train_horizon, @@ -270,7 +270,7 @@ class TestMakeVerticalTimeSeries: ... the history of order totals is not long enough. """ with pytest.raises(RuntimeError): - order_history.make_vertical_time_series( + order_history.make_vertical_ts( pixel_id=good_pixel_id, predict_day=bad_predict_at.date(), train_horizon=train_horizon, @@ -284,7 +284,7 @@ class TestMakeVerticalTimeSeries: ... the history of order totals can never be long enough. """ with pytest.raises(RuntimeError): - order_history.make_vertical_time_series( + order_history.make_vertical_ts( pixel_id=good_pixel_id, predict_day=good_predict_at.date(), train_horizon=999, @@ -292,13 +292,13 @@ class TestMakeVerticalTimeSeries: class TestMakeRealTimeTimeSeries: - """Test the `OrderHistory.make_real_time_time_series()` method.""" + """Test the `OrderHistory.make_realtime_ts()` method.""" @pytest.mark.parametrize('train_horizon', test_config.TRAIN_HORIZONS) def test_wrong_pixel(self, order_history, good_predict_at, train_horizon): """A `pixel_id` that is not in the `grid`.""" with pytest.raises(LookupError): - order_history.make_real_time_time_series( + order_history.make_realtime_ts( pixel_id=999_999, predict_at=good_predict_at, train_horizon=train_horizon, @@ -309,7 +309,7 @@ class TestMakeRealTimeTimeSeries: self, order_history, good_pixel_id, good_predict_at, train_horizon, ): """The time series come as `pd.Series`.""" - result = order_history.make_real_time_time_series( + result = order_history.make_realtime_ts( pixel_id=good_pixel_id, predict_at=good_predict_at, train_horizon=train_horizon, @@ -318,9 +318,9 @@ class TestMakeRealTimeTimeSeries: training_ts, _, actuals_ts = result assert isinstance(training_ts, pd.Series) - assert training_ts.name == 'total_orders' + assert training_ts.name == 'n_orders' assert isinstance(actuals_ts, pd.Series) - assert actuals_ts.name == 'total_orders' + assert actuals_ts.name == 'n_orders' @pytest.mark.parametrize('train_horizon', test_config.TRAIN_HORIZONS) def test_time_series_have_correct_length1( @@ -341,7 +341,7 @@ class TestMakeRealTimeTimeSeries: config.SERVICE_START, 0, ) - result = order_history.make_real_time_time_series( + result = order_history.make_realtime_ts( pixel_id=good_pixel_id, predict_at=predict_at, train_horizon=train_horizon, ) @@ -372,7 +372,7 @@ class TestMakeRealTimeTimeSeries: """ assert good_predict_at.hour == test_config.NOON - result = order_history.make_real_time_time_series( + result = order_history.make_realtime_ts( pixel_id=good_pixel_id, predict_at=good_predict_at, train_horizon=train_horizon, @@ -400,7 +400,7 @@ class TestMakeRealTimeTimeSeries: self, order_history, good_pixel_id, good_predict_at, train_horizon, ): """The `frequency` is the number of weekly time steps.""" - result = order_history.make_real_time_time_series( + result = order_history.make_realtime_ts( pixel_id=good_pixel_id, predict_at=good_predict_at, train_horizon=train_horizon, @@ -425,7 +425,7 @@ class TestMakeRealTimeTimeSeries: ... the history of order totals is not long enough. """ with pytest.raises(RuntimeError): - order_history.make_real_time_time_series( + order_history.make_realtime_ts( pixel_id=good_pixel_id, predict_at=bad_predict_at, train_horizon=train_horizon, @@ -439,6 +439,6 @@ class TestMakeRealTimeTimeSeries: ... the history of order totals can never be long enough. """ with pytest.raises(RuntimeError): - order_history.make_real_time_time_series( + order_history.make_realtime_ts( pixel_id=good_pixel_id, predict_at=good_predict_at, train_horizon=999, )