{"id":30990614,"url":"https://github.com/finite-sample/incline","last_synced_at":"2025-10-18T17:51:01.225Z","repository":{"id":62570865,"uuid":"181930663","full_name":"finite-sample/incline","owner":"finite-sample","description":"Estimate Trend at a Point in a Noisy Time Series","archived":false,"fork":false,"pushed_at":"2025-02-14T05:56:50.000Z","size":517,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-08T21:34:51.669Z","etag":null,"topics":["derivative","noisy-data","slope","time-series"],"latest_commit_sha":null,"homepage":"","language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/finite-sample.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-04-17T16:37:06.000Z","updated_at":"2025-06-22T03:40:11.000Z","dependencies_parsed_at":"2025-02-14T14:45:28.096Z","dependency_job_id":null,"html_url":"https://github.com/finite-sample/incline","commit_stats":null,"previous_names":["soodoku/incline","finite-sample/incline"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/finite-sample/incline","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/finite-sample%2Fincline","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/finite-sample%2Fincline/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/finite-sample%2Fincline/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/finite-sample%2Fincline/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/finite-sample","download_url":"https://codeload.github.com/finite-sample/incline/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/finite-sample%2Fincline/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274866544,"owners_count":25364542,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-12T02:00:09.324Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["derivative","noisy-data","slope","time-series"],"created_at":"2025-09-12T19:51:03.850Z","updated_at":"2025-10-18T17:51:01.219Z","avatar_url":"https://github.com/finite-sample.png","language":"Jupyter Notebook","funding_links":[],"categories":[],"sub_categories":[],"readme":"incline: Estimate Trend at a Particular Point in a Noisy Time Series\n-----------------------------------------------------------------------\n\n.. image:: https://img.shields.io/pypi/v/incline.svg\n    :target: https://pypi.python.org/pypi/incline\n.. image:: https://static.pepy.tech/badge/incline\n    :target: https://pepy.tech/project/incline\n.. image:: https://github.com/finite-sample/incline/actions/workflows/ci.yml/badge.svg\n    :target: https://github.com/finite-sample/incline/actions?query=workflow%3Aci\n.. image:: https://img.shields.io/badge/docs-github.io-blue\n    :target: https://finite-sample.github.io/incline/\n\nTrends in time series are valuable. If the cost of a product rises suddenly, it likely indicates a sudden shortfall in supply or a sudden rise in demand. If the cost of claims filed by a patient rises sharply, it may suggest rapidly worsening health. But how do we estimate the trend at a particular time in a noisy time series? Smooth the time series using any one of the many methods, local polynomials or via GAMs or similar such methods, and then estimate the derivative(s) of the function at the chosen point in time.\n\nThe package provides a couple of ways of approximating the underlying function for the time series:\n\n- fitting a local higher order polynomial via Savitzky-Golay over a window of choice\n\n- fitting a smoothing spline\n\nThe package provides a way to estimate the first and second derivative at any given time using either of those methods. Beyond these smarter methods, the package also provides a way a naive estimator of slope---average change when you move one-step forward (step = observed time units) and one-step backward. The users can also calculate average or max. slope over a time window (over observed time steps).\n\nThe difference between naive estimates and estimates based on smoothed time series can be substantial. In the `example \u003chttps://github.com/finite-sample/incline/blob/master/incline/examples/incline_example.ipynb\u003e`__ we provide, the correlation is -.47.\n\nClarification\n~~~~~~~~~~~~~\n\nSometimes we want to know what the \"trend\" was over a particular time\nwindow. But what that means is not 100% clear. For a synopsis of the\nissues, see\n`here \u003chttp://gbytes.gsood.com/2018/06/22/talking-on-a-tangent/\u003e`__.\n\nUnderlying Machinery\n~~~~~~~~~~~~~~~~~~~~\n\nSavitzky-Golay\n^^^^^^^^^^^^^^\n\nFilter the time series using local polynomials and get an estimate of\nthe derivative in one shot. For more information, see the `Python\ndcoumentation \u003chttps://docs.scipy.org/doc/scipy-0.16.1/reference/generated/scipy.signal.savgol_filter.html\u003e`__\nand\n`Wikipedia \u003chttps://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter\u003e`__\n\nUnivariate Splines\n^^^^^^^^^^^^^^^^^^\n\nFind more details `here \u003chttps://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.UnivariateSpline.html\u003e`__\n\n\nAssumption\n~~~~~~~~~~~~~~~~~~~\n\nSilly as it is, for now, we assume that the time series is a) complete, and b) increases with unit time intervals.\n\nAPI\n~~~\n\nThe package wraps the functions for doing local smoothing and derivative\nestimation for a standardized interface. We use this standard interface\nto estimate the trend at a particular set of points in parallel for\nthousands of time series.\n\nThe package ``incline`` exposes 4 functions:\n\n1. ``naive_trend``:\n    \n    **Input:**\n    \n    -  df: pandas dataFrame `time series\n       object \u003chttps://pandas.pydata.org/pandas-docs/stable/timeseries.html\u003e`__\n    \n    **Functionality:**\n    \n    -  estimates the derivative at a location by taking the average of\n       change when you move one unit to the right and change when you move\n       one unit to the left.\n    \n    **Output:**\n    \n    dataframe with 6 columns (smoothed value column just has ``None``):\n    ``datetime, function_order (value of the polynomial order), smoothed_value, derivative_method, derivative_order, derivative_value``.\n\n2. ``spline_trend``:\n\n    **Input:**\n    \n    -  df: pandas dataFrame `time series\n       object \u003chttps://pandas.pydata.org/pandas-docs/stable/timeseries.html\u003e`__\n    -  function\\_order: spline order (default is 3)---fitting with cubic\n       splines. The knot placement is determined by the smoothing factor s.\n    -  derivative\\_order: (0, 1, 2, ... with default as 1)\n    -  s: smoothing factor. the total unnormalized global cost that we are willing to bear. larger values give more smoothed estimates. See the \n       `documentation \u003chttps://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.UnivariateSpline.html\u003e`__ for details. \n    \n    **Functionality:**\n    \n    Interpolates time series with splines of 'function\\_order'. And then\n    calculates the derivative\\_order using the smoothed function.\n    \n    **Output:**\n    \n    dataframe with 6 columns:\n    ``datetime, function_order (value of the polynomial order), smoothed_value, derivative_method, derivative_order, derivative_value``.\n    \n    A row can be 2012-01-01, \"spline\", 2, 1, 0\n\n3. ``sgolay_trend``:\n\n    **Input:**\n    \n    -  df pandas dataFrame `time series\n       object \u003chttps://pandas.pydata.org/pandas-docs/stable/timeseries.html\u003e`__\n    -  window\\_size: default is 15\n    -  function\\_order: polynomial order (default is 3)\n    -  derivative\\_order: (0, 1, 2, ... with default as 1)\n    \n    **Functionality:**\n    \n    Interpolates time series with savitzky-golay using polynomials of\n    'function\\_order'. And then calculates the derivative\\_order using the\n    smoothed function.\n    \n    **Output:**\n    \n    dataframe with 6 columns:\n    ``datetime, function_order (value of the polynomial order), smoothed_value, derivative_method, derivative_order, derivative_value``.\n    \n    Sample row: 2012-01-01, \"savitzky-golay\", 2, 1, 0\n\n4. ``trending``:\n\n    **Input:**\n    \n    -  df\\_list: list of outputs (dataframes) from ``savitzky_golay_trend``\n       or ``spline_trend`` with a new column called 'id' that identifies the\n       time series\n    -  derivative\\_order: (1 or 2)\n    -  k: number of latest time periods to consider.\n    -  max\\_or\\_avg: \"max\" or \"avg\"\n    \n    **Functionality:**\n    \n    for each item in the list, calculate either the max or the average\n    (depending on max\\_or\\_avg) of the Yth derivative (based on the\n    derivative\\_order) over the last k time\\_periods (based on the input).\n    It then orders the list based on max to min.\n    \n    For instance, for derivative\\_order = 1, max\\_or\\_avg = \"max\",\n    time\\_periods = 3, for each item in the list, the function will take the\n    max of the last 3 rows of the dataframe entries identifying the 1st\n    derivative.\n    \n    So each item in the list produces one number (max or avg.). We then\n    produce a new dataframe with 2 columns: ``id, max_or_avg``\n    \n    **Output:**\n    \n    Dataframe with 2 columns: ``id, max_or_avg``\n\nInstallation\n~~~~~~~~~~~~\n\n::\n\n    pip install incline\n\nUsage\n~~~~~\n\n::\n\n    from incline import spline_trend\n\n    locpol = spline_trend(time_series, , ...)\n\nExamples\n~~~~~~~~\n\nPlease look at this `notebook \u003chttps://github.com/finite-sample/incline/blob/master/incline/examples/incline_example.ipynb\u003e`_. for how to use incline using data from the stock market.\n\nLicense\n~~~~~~~\n\nThe package is released under the `MIT\nLicense \u003chttps://opensource.org/licenses/MIT\u003e`__.\n\nAuthors\n~~~~~~~\n\nSuriyan Laohaprapanon and Gaurav Sood\n\nAdditional Reading\n~~~~~~~~~~~~~~~~~~\n\nWhile we don't provide this in the package but you could approximate the function using:\n\n1. Penalized cubic splines using GAMS via `pyGAM \u003chttps://github.com/dswah/pyGAM\u003e`__. For more information, see\nthese `lecture notes \u003chttps://web.stanford.edu/class/stats202/content/lec17.pdf\u003e`__  \n\n2. Or, `nonparametrically \u003chttps://pythonhosted.org/PyQt-Fit/NonParam_tut.html\u003e`__\n\nAnd here's a paper on `Derivative Estimation with Local Polynomial Fitting \n\u003chttps://dl.acm.org/citation.cfm?id=2502590\u003e`__\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffinite-sample%2Fincline","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffinite-sample%2Fincline","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffinite-sample%2Fincline/lists"}