{"id":17316077,"url":"https://github.com/ankostis/rollstats","last_synced_at":"2026-04-19T10:31:49.559Z","repository":{"id":80664851,"uuid":"489605201","full_name":"ankostis/rollstats","owner":"ankostis","description":"Calculate rolling avg, var \u0026 stdev in Python \u0026 C++ code","archived":false,"fork":false,"pushed_at":"2022-05-08T10:07:55.000Z","size":17,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-27T02:13:56.300Z","etag":null,"topics":["cpp","data-science","python","sample-code","statistics"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ankostis.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2022-05-07T07:40:20.000Z","updated_at":"2023-07-19T06:06:02.000Z","dependencies_parsed_at":null,"dependency_job_id":"669721cb-d4e8-445a-a1a1-74359789b3ac","html_url":"https://github.com/ankostis/rollstats","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ankostis/rollstats","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ankostis%2Frollstats","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ankostis%2Frollstats/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ankostis%2Frollstats/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ankostis%2Frollstats/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ankostis","download_url":"https://codeload.github.com/ankostis/rollstats/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ankostis%2Frollstats/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268493112,"owners_count":24258961,"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-08-03T02:00:12.545Z","response_time":2577,"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":["cpp","data-science","python","sample-code","statistics"],"created_at":"2024-10-15T13:11:33.397Z","updated_at":"2026-04-19T10:31:44.522Z","avatar_url":"https://github.com/ankostis.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Rollstats\n\nCalculate rolling *avg*, *var* \u0026 *stdev*, in Python \u0026 C++ code\n\n## 1. Math formulas\n\nAdapted from [The Mindful Programmer (jonisalonen)](https://jonisalonen.com/2014/efficient-and-accurate-rolling-standard-deviation/)\n(had also [replied earlier in this SO](https://stackoverflow.com/a/14638138/548792)).\n\nIn that post, the rolling formulas are eventually given like that\n(transcribed here with an iterative viepoint):\n\n$$\n\\newcommand{\\Var}{\\operatorname{Var}}\n\\begin{align}\n    \\overline{x_{new}} \u0026= \\overline{x_{old}}  + \\frac{x_{inp} - x_{out}}{N}  \\\\\n\n    \\Var[x_{new}] \u0026= \\Var[x_{old}] + (x_{inp} - x_{out})\n        \\times (x_{inp} - \\overline{x_{new}} + x_{out} - \\overline{x_{old}})  \\\\\n\n    \\sigma[x] \u0026= \\sqrt{|\\Var[x]|}\n\\end{align}\n$$\n\nthat depend on the numbers *entering* and *exiting* the\n$N$ sized circular-buffer, respectively:\n\n- $x_{inp}$\n- $x_{out}$\n\nand on the mean values of that buffer, *before* and *after* the swap, respectively:\n\n- $\\overline{x_{old}}$\n- $\\overline{x_{new}}$\n\n**NOTE:** the original post lacked the  absolute ($|...|$) inside the root($\\sqrt{}$),\ndiscovered its need by experiments.  Conventionally calculated variance\n(with sum-of-squared-diffs) is never negative.\n\n## 2. Implementations\n\nAll classes compute the *average*, *variance* and *standard-deviation* after\neach new element has been inserted in the circular buffer.\n\n- `rollstats.py` - start with an empty OR a pre-filled circular-buffer.\n- `rollstats1.cpp` - start with an empty std::vector (runtime sized).\n- `rollstats2.cpp` - compile-sized array pre-filled with the same init-value on runtime\n\n## 3. Quickstart\n\n### 3.1. Build\n- Python does not need any extra library.\n- Build C-impls:\n\n  ```bash\n  g++ -Wall -Wextra -Werror -std=c++20 -pie rollstats2.cpp -o rollstats2.exe\n  ```\n\n\n### 3.2. Command-line\n\n#### 3.2.1. Python\n\n```bash\n./rollstats.py 3  10 10 10 12 14 12 16 20 12 17 35 10 10 10 10\n0: 10 --\u003e 10.00 ± 0.00\n1: 10 --\u003e 10.00 ± 0.00\n2: 10 --\u003e 10.00 ± 0.00\n3: 12 --\u003e 10.67 ± 1.15\n4: 14 --\u003e 12.00 ± 2.00\n5: 12 --\u003e 12.67 ± 1.15\n6: 16 --\u003e 14.00 ± 2.00\n7: 20 --\u003e 16.00 ± 4.00\n8: 12 --\u003e 16.00 ± 4.00\n9: 17 --\u003e 16.33 ± 4.04\n10: 35 --\u003e 21.33 ± 12.10\n11: 10 --\u003e 20.67 ± 12.90\n12: 10 --\u003e 18.33 ± 14.43\n13: 10 --\u003e 10.00 ± 0.00\n14: 10 --\u003e 10.00 ± 0.00\n```\n\n##### 3.2.2. C++, start with an empty `std::vector`\n\n```bash\n./rollstats1 3  10 10 10 12 14 12 16 20 12 17 35 10 10 10 10\n0: 10 --\u003e 10 ± 0\n1: 10 --\u003e 10 ± 0\n2: 10 --\u003e 10 ± 0\n3: 12 --\u003e 10.67 ± 1\n4: 14 --\u003e 12 ± 1.732\n5: 12 --\u003e 12.67 ± 1\n6: 16 --\u003e 14 ± 1.732\n7: 20 --\u003e 16 ± 3.873\n8: 12 --\u003e 16 ± 3.873\n9: 17 --\u003e 16.33 ± 4\n10: 35 --\u003e 21.33 ± 12.08\n11: 10 --\u003e 20.67 ± 12.88\n12: 10 --\u003e 18.33 ± 14.42\n13: 10 --\u003e 10 ± 0\n14: 10 --\u003e 10 ± 0\n```\n\n##### 3.2.3. C++, compile-sized \u0026 pre-filled with a single value\n\nNotice that less items are given, since the 1st `10` is fills the entire\ncircular array (by default, 3-elements sized):\n\n```bash\n/rollstats2.exe 10 12 14 12 16 20 12 17 35 10 10 10 10\n1: 12 --\u003e 10.67 ± 1\n2: 14 --\u003e 15.33 ± 9.055\n3: 12 --\u003e 19.33 ± 14.76\n4: 16 --\u003e 20.67 ± 15.56\n5: 20 --\u003e 22.67 ± 16.43\n6: 12 --\u003e 22.67 ± 16.43\n7: 17 --\u003e 23 ± 16.64\n8: 35 --\u003e 28 ± 15.72\n9: 10 --\u003e 27.33 ± 14.59\n10: 10 --\u003e 25 ± 11.18\n11: 10 --\u003e 16.67 ± 12.88\n12: 10 --\u003e 16.67 ± 12.88\n```\n\n### 3.3. Python code\n\n#### 3.3.1. Auto-populate circular-buffer from the very 1st item\n\n...like the command-line does:\n\n```python\nwsize = 3\nmain(wsize, 10, 10, 10, 12, 14, 12, 16, 20, 12, 17, 35, 10, 10, 10, 10)\n```\n\n#### 3.3.2. Start with a pre-filled list\n\n...alternative run to validate the correctness of the results:\n\n```python\nize = 3\nl = [10, 10, 10, 12, 14, 12, 16, 20, 12, 17, 35, 10, 10, 10, 10]\nrs = RollingStats(l[:wsize])\nitems = l[wsize:]\nstats = rs.roll_stats(items)\nprint(\"\\n\".join(\n    f\"{i}: {x_inp} --\u003e {avg:.2f} ± {stdev:.2f}\"\n    for i, (x_inp, (avg, stdev)) in enumerate(zip(items, stats))))\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fankostis%2Frollstats","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fankostis%2Frollstats","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fankostis%2Frollstats/lists"}