diff --git a/notebooks/Gas Toggle Demo.ipynb b/notebooks/Gas Toggle Demo.ipynb index 7d8a5d5..2f5d0a6 100644 --- a/notebooks/Gas Toggle Demo.ipynb +++ b/notebooks/Gas Toggle Demo.ipynb @@ -116,7 +116,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.0" + "version": "3.6.3" } }, "nbformat": 4, diff --git a/notebooks/Threshold_detection.ipynb b/notebooks/Threshold_detection.ipynb new file mode 100644 index 0000000..7f064a1 --- /dev/null +++ b/notebooks/Threshold_detection.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Intro #\n", + "\n", + "This analysis counts the total amount of time - and total consumption when - a series goes above (or below) a certain threshold.\n", + "It also returns the count of these occurances." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Imports ##" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import opengrid as og\n", + "from opengrid import datasets\n", + "import numpy as np\n", + "\n", + "plt = og.plot_style()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Prepare data ##" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# We have a dataset prepared that contains gas sensor data in W on a minutely resolution\n", + "df = datasets.get('gas_dec2016_min')\n", + "df = df['313b']\n", + "\n", + "ts = df.squeeze()\n", + "\n", + "threshold = 25000\n", + "freq = 'min'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Plot ##" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.plot(ts)\n", + "plt.axhline(threshold, color='r')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "result = og.analysis.threshold_detection(ts, threshold, freq=freq)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "result" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opengrid/library/analysis.py b/opengrid/library/analysis.py index c67e520..626d93e 100644 --- a/opengrid/library/analysis.py +++ b/opengrid/library/analysis.py @@ -69,6 +69,37 @@ def do_analysis(self, agg, starttime=dt.time.min, endtime=dt.time.max): self.result = pd.DataFrame() +def threshold_detection(ts, threshold, direction='above', freq=None): + """ + Describe timeseries in regards to a specified threshold + + :param ts: Pandas Series + :param threshold: number + :param direction: string (above or below) + :param freq: string + :return: dict + """ + if freq is not None: + ts = ts.resample(freq).sum() + + if direction == 'above': + thresh_ts = ts > threshold + elif direction == 'below': + thresh_ts = ts < threshold + else: + raise ValueError("direction can only be 'above' or 'below'.") + + duration = len(ts[thresh_ts]) + amount = (ts[thresh_ts] - threshold).sum() + + on_toggles = thresh_ts + shifted = np.logical_not(on_toggles.shift(1)) + result = on_toggles & shifted + count = result.sum() + + return dict([('Total_amount', amount), ('Total_duration', duration), ('count', count)]) + + def standby(df, resolution='24h', time_window=None): """ Compute standby power diff --git a/opengrid/tests/test_analyses.py b/opengrid/tests/test_analyses.py index 796eb92..961d791 100644 --- a/opengrid/tests/test_analyses.py +++ b/opengrid/tests/test_analyses.py @@ -64,6 +64,20 @@ def test_load_factor(self): self.assertIsInstance(ts, pd.Series) self.assertAlmostEqual(175.0345212009457, (lf2 * 800).iloc[0]) + def test_threshold_detection(self): + df = datasets.get('gas_dec2016_min') + df = df['313b'] + + ts = df.squeeze() + + threshold = 25000 + freq = 'min' + + result = og.analysis.threshold_detection(ts, threshold, freq=freq) + + self.assertEqual(result['count'], 19) + self.assertEqual(result['Total_duration'], 22) + self.assertAlmostEqual(result['Total_amount'], 24335.314876027405) if __name__ == '__main__': unittest.main()