Open-source project
joshday/OnlineStats.jl avatar
joshday/OnlineStats.jl

OnlineStats.jl: statistics that update one observation at a time in constant memory

⚡ Single-pass algorithms for statistics

900 stars67 forksJuliaMIT

At a glance

What is it?
OnlineStats.jl is a Julia package of single-pass algorithms for statistics, models and data visualisation, where every estimator is updated with fit! and read back with value while using O(1) memory. The API is small enough to learn in a minute, and the design fits streaming data rather than batch analysis.
Who is it for?
Adopt OnlineStats.jl if you are working in Julia and need estimators that can be updated one observation at a time without holding the data, whether that is a stream, a log file or a dataset that will not fit in memory. Do not adopt it when you need exact two-pass results, since the estimators are approximations, and not when you need a deep catalogue of specialised statistical tests.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 32 days ago.
What is it written in?
Mainly Julia, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem: the estimator is small, the data is not

Most statistical software assumes the data fits in memory twice over. You compute a mean by reading the vector, you compute a variance by reading it again, and the cost of the second pass is invisible because the data was already loaded. That assumption breaks in two situations: a stream that arrives once and cannot be replayed, and a dataset that is larger than the memory you have.

OnlineStats.jl is a Julia package of online algorithms for statistics, models and big data visualisation. The package description is precise about the approach: high-performance single-pass algorithms, updated one observation at a time, using O(1) memory, and suited to streaming and big data.

The O(1) claim is the heart of it. An online estimator holds a fixed amount of state, a running mean holds a count and a sum, a running variance holds those plus a sum of squares, and neither grows with the number of observations. So the memory cost of tracking ten thousand statistics over a billion rows is the same as tracking them over ten rows. That is what makes the library usable on a stream.

The audience is Julia users doing data analysis where the data is large, arrives incrementally, or both. It is a library of estimators, not a plotting package or a workflow system, and the repository topics place it firmly in the online algorithms and streaming data space, with stochastic approximation named alongside.

The package is published with a Journal of Open Source Software paper, has a DOI, and is documented with a stable and a latest version of the docs, which are the marks of a package that has been used as a dependency rather than written for one project.

The contract: fit! to update, value to read

The API is two functions, and the whole library can be understood from them.

fit! updates a statistic with new data. It accepts a single observation, and it accepts an iterable, in which case the iterable is consumed one element at a time. value reads the current state back, and for a collection of statistics it returns a tuple of values in the order the statistics were declared.

That is the entire interface, and it is why the library composes with everything else in the Julia ecosystem. Any object that implements fit! and value is a valid statistic, and the library's own estimators are just that protocol applied to different algorithms. A model that can be updated the same way fits into the same Series as a running mean.

The design also settles a question that usually causes friction: what does the return value of fit! mean? The quickstart does not use it. You call fit! for its effect on the object, and you call value when you want the number. The alternative convention, where the update function returns the new value, is not used here.

The state is held by mutation rather than by rebuilding, which is the whole point. A conventional mean over a vector allocates a new sum each time you recompute it; an online mean adds to a field. Over a large stream that difference is the difference between a workload that fits in your memory budget and one that does not.

Installing the package and running your first estimator

The quickstart in the project documentation is a complete session, and it starts with the standard package manager:

julia
import Pkg

Pkg.add("OnlineStats")

using OnlineStats

Then you build the statistics you want. The example creates three of them in one object:

julia
# Create several statistics
o = Series(Mean(), Variance(), Extrema())

A Series is a collection of statistics kept side by side and updated together, which saves a second pass over the data if you want a mean, a variance and the extremes at once.

Updating is a single call, and the same call handles a scalar and a whole array, because fit! over an iterable iterates:

julia
# Update with single data point
fit!(o, 1.0)

# Iterate through and update with lots of data
fit!(o, randn(10^6))

Reading the results back is the value call, and for a Series it returns the values in declaration order:

julia
# Get the values of the statistics
value(o)  # (value(mean), value(variance), value(extrema))

So a working session is under ten lines: add, use, construct, update, read. The generated documentation for the package lives at joshday.github.io, with separate stable and latest builds, and the package ships a docs/ directory, a notebooks/ directory and a test/ directory in the repository.

Series and the estimator catalogue

The Series constructor takes statistics as arguments, and the argument list is effectively the catalogue of what the library can compute. In the quickstart it is Mean, Variance and Extrema, one for the average, one for the spread and one for the minimum and maximum.

What the estimator list contains is not limited to those three. The package title covers statistics, models and big data visualisation, so the same update-and-read protocol is used for more than descriptive statistics, and the repository topics include stochastic approximation, which is the family of algorithms that update an estimate towards a target using noisy steps rather than a closed form solution.

The Series design carries the practical consequences of that protocol. Because the statistics in a Series are updated together in one pass, adding a statistic to a Series costs almost nothing in time, only a constant in memory. The cost of that convenience is that every statistic in the Series is fitted to the same data, so a Series cannot be split across subsets without splitting the Series.

There is also a readability gain. The list of statistics at the top of your script is a description of what you are measuring, and it stays readable as the number grows. A conventional approach with a DataFrame and a describe call hides the same information behind a runtime reflection, which is fine for exploration and awkward for a long lived pipeline.

For the catalogue itself, the source directory is the place to look, and the documentation pages for each estimator are the place to read about the specific algorithm and its assumptions, since the project description does not enumerate the estimators beyond the three used in the quickstart.

Releases, the paper and who has worked on it

The release history has an odd shape. On 2026-06-11 three tags were published within about a minute of each other: v1.7.4, v0.27.0 and v0.26.1. Two different major series, one minute apart, is a sign of a version numbering transition rather than three independent releases, and it is the kind of detail that makes you check the registry before pinning a dependency.

The repository is not archived and the last push was on 2026-09-21, so the package is being worked on. The current version line and the last tag are close enough that the difference is unlikely to matter for a statistical library, but pinning v1.7.4 rather than tracking a branch is the safe habit.

The package has a Journal of Open Source Software paper with DOI 10.21105/joss.01816, and the repository carries a paper/ directory alongside the source. It also has a citation badge and a dependents badge, which record that other packages depend on it.

The authorship history is documented in the project description. Josh Day is the primary author. Tom Breloff made significant early contributions, and many of the algorithms were developed under the mentorship of Hua Zhou. For a package whose estimators are the product, that provenance matters more than it would for a utility library, because the algorithm choices are where the correctness lives.

The contributing guidance is brief: pull requests are welcome, and major changes are best discussed first by issue, email or slack with the maintainer. The MIT licence means the code can be used, modified and redistributed in commercial work with the notice retained.

Where single-pass is the wrong shape, and what the alternative costs

The limitation follows from the design rather than being a defect. An online estimator is an approximation in most cases, because it commits to an answer before it has seen the rest of the data. A variance computed in one pass, a quantile estimated from a sketch, a model fitted by stochastic approximation, all of these have error that depends on the update order and on the data, and none of them gives you the option to revisit an earlier decision.

That is the right trade when the data cannot be revisited, and the wrong trade when it can. If your data fits in memory and you want the exact two-pass answer, the conventional approach is both simpler and more accurate: load it, compute it, done. The alternative to OnlineStats is not a competing Julia package, it is the ordinary batch path, and the difference in approach is that the batch path is allowed to look at the data twice.

There is a second, quieter cost. Online statistics are order dependent, which means a distributed or parallel implementation has to decide how partial results combine, and not every estimator composes cleanly that way. If your data is sharded across machines, that decision is a design problem the library does not solve for you, and the project description does not document a merge protocol.

The third limit is documentation. The package description is short, the quickstart is short, and the depth lives in the generated documentation and in the source. That is normal for a Julia package, where the source is the reference, but it does mean that judging whether the library supports the estimator you need means reading the docs directory or the estimator source.

So the decision is: reach for OnlineStats.jl when a second pass is not an option, and for the ordinary path when it is.

Editorial conclusion

Adopt OnlineStats.jl if you are working in Julia and need estimators that can be updated one observation at a time without holding the data, whether that is a stream, a log file or a dataset that will not fit in memory. Do not adopt it when you need exact two-pass results, since the estimators are approximations, and not when you need a deep catalogue of specialised statistical tests. Before you commit, read the stable documentation for the estimator you care about, check the algorithm list in the docs directory, and confirm that a single pass over your data is enough, because OnlineStats is built for the case where a second pass is not an option.

Frequently asked questions

How do I install and use OnlineStats.jl?

Add it with Pkg.add("OnlineStats"), then create statistics such as Series(Mean(), Variance(), Extrema()), update them with fit!, which takes either a single observation or an iterable, and read the results with value, which returns the values in declaration order.

What memory does OnlineStats.jl use?

The package states that its algorithms use O(1) memory, because each estimator holds a fixed amount of state that does not grow with the number of observations. That is what makes the estimators usable on a stream or on data larger than memory.

Is OnlineStats.jl suitable for streaming data?

Yes. It is described as a set of online algorithms for statistics, models and big data visualisation, updated one observation at a time, and the repository topics name online algorithms and streaming data directly. The estimators are order dependent, so combining partial results across shards is a decision the caller has to make.

What licence is OnlineStats.jl under?

MIT, with the LICENSE file at the root of the repository, so the code can be used and modified in commercial work provided the notice is kept. The package also has a Journal of Open Source Software paper with DOI 10.21105/joss.01816.

Which version of OnlineStats.jl should I depend on?

The repository published v1.7.4 on 2026-06-11, and on the same day also published v0.27.0 and v0.26.1, which suggests a version numbering transition. The last push was on 2026-09-21, so pinning an explicit released version is safer than tracking a branch.

Official sources

  1. joshday/OnlineStats.jl on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/joshday-onlinestats-jl.svg)](https://hysenlabs.com/projects/joshday-onlinestats-jl)

Was this useful?