# Common data utilities for time series

**URL:** <https://discourse.julialang.org/t/common-data-utilities-for-time-series/137104>\
**Category:** General Usage\
**Tags:** data\
**Created:** [May 13, 2026, 2:39pm UTC](https://discourse.julialang.org/t/common-data-utilities-for-time-series/137104 "2026-05-13T14:39:19Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![langestefan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/langestefan/32/207923_2.png) [@langestefan](https://discourse.julialang.org/u/langestefan)\
**Post date:** [May 13, 2026, 2:39pm UTC](https://discourse.julialang.org/t/common-data-utilities-for-time-series/137104/1 "2026-05-13T14:39:20Z")

</div>

I frequently find myself having to cleanup and process raw ‘real’ data. I am really not a data person, but I think this is called data plumbing. _And to be honest, I don’t have much fun doing it 🙂_

Typical operations include:

- Finding gaps in the data
- Imputation
- ffill / bfill / Interpolation
- Outlier detection and correction
- Resampling
- Identifying usable sections in noisy data

Some low level functions for these operations are provided by packages like DSP.jl, DataFrames.jl, Interpolations.jl. But it takes some work to hook them up to your specific time-aware data source and format, and as a result the past few years I ended up writing multiple implementations of `resample`.

So ideally what I want is a very lightweight package that works directly on Tables.jl data sources, preferably lazily or in place with minimal copying. All you would need to know is: what is my data axis? What is my time axis? Which operations do I want to apply? And then just do it. That way we don’t have to maintain our own time-aware types or index columns, like TSFrames.jl and TimeSeries.jl do. It should also be trivial to stack multiple operations using for example Chain.jl, operate on multiple columns with multithreading, add new processing functions, either directly or through extensions.

Does such a package exist, and did I miss it? Should it exist? Any comments or ideas are welcome.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [May 13, 2026, 3:15pm UTC](https://discourse.julialang.org/t/common-data-utilities-for-time-series/137104/2 "2026-05-13T15:15:58Z")

</div>

I’m almost sure you can do all that with GMT.jl. Some recipes are already _high level_ implemented, others would probably need to dig in docs. See [these examples](https://www.generic-mapping-tools.org/GMTjl_doc/tutorials/signal/signal.html)

---

<div class="post-metadata">

**Author:** ![langestefan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/langestefan/32/207923_2.png) [@langestefan](https://discourse.julialang.org/u/langestefan)\
**Post date:** [May 13, 2026, 3:44pm UTC](https://discourse.julialang.org/t/common-data-utilities-for-time-series/137104/3 "2026-05-13T15:44:52Z")

</div>

Thanks! That definitely has some useful features. I didn’t expect to find that in a package for geographic data. My idea was to have a package that is focused on tabular and time-series data.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [May 13, 2026, 4:40pm UTC](https://discourse.julialang.org/t/common-data-utilities-for-time-series/137104/4 "2026-05-13T16:40:48Z")

</div>

> [@langestefan](#):
>
> I didn’t expect to find that in a package for geographic data.

GMT is _Generic_. Both geographic and Cartesian.

---

<div class="post-metadata">

**Author:** ![Jake](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jake/32/46007_2.png) [@Jake](https://discourse.julialang.org/u/Jake)\
**Post date:** [May 13, 2026, 5:53pm UTC](https://discourse.julialang.org/t/common-data-utilities-for-time-series/137104/5 "2026-05-13T17:53:56Z")

</div>

Give [impute](https://invenia.github.io/Impute.jl/latest/) a try. I was quite impressed.

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [May 13, 2026, 6:04pm UTC](https://discourse.julialang.org/t/common-data-utilities-for-time-series/137104/6 "2026-05-13T18:04:57Z")

</div>

TableTransforms.jl has plenty of transforms for Tables.jl.

---

<div class="post-metadata">

**Author:** ![langestefan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/langestefan/32/207923_2.png) [@langestefan](https://discourse.julialang.org/u/langestefan)\
**Post date:** [May 13, 2026, 6:40pm UTC](https://discourse.julialang.org/t/common-data-utilities-for-time-series/137104/7 "2026-05-13T18:40:49Z")

</div>

Yes, that is a very useful package. Not the data plumbing methods I’m looking for. But could be easily composed with such methods

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [May 13, 2026, 8:31pm UTC](https://discourse.julialang.org/t/common-data-utilities-for-time-series/137104/8 "2026-05-13T20:31:10Z")

</div>

As a side comment, notice that we’ve built TableTransforms.jl on top of the TransformsBase.jl API, which is implemented in various other downstream packages like GeoStatsTransforms.jl for GeoTables.jl. If you come up with new transforms for time series, try to implement the same API.

My impression is that many time series transforms could simply be added to TableTransforms.jl as they only assume order of rows. If the transform relies on actual time differences (e.g. lags), then it makes sense to store them in a separate package.

---

<div class="post-metadata">

**Author:** ![zdenek\_hurak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zdenek_hurak/32/53118_2.png) [@zdenek\_hurak](https://discourse.julialang.org/u/zdenek_hurak)\
**Post date:** [May 15, 2026, 7:51am UTC](https://discourse.julialang.org/t/common-data-utilities-for-time-series/137104/9 "2026-05-15T07:51:16Z")

</div>

> [@langestefan](#):
>
> I think this is called data plumbing

I encounter the names like data wrangling and data munging even more frequently. Could help when searching for some more discussions.

---

<div class="post-metadata">

**Author:** ![Boris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/boris/32/3306_2.png) [@Boris](https://discourse.julialang.org/u/Boris)\
**Post date:** [May 15, 2026, 9:45am UTC](https://discourse.julialang.org/t/common-data-utilities-for-time-series/137104/10 "2026-05-15T09:45:37Z")

</div>

I work with Time Series all the time and I am a big fan of the `TimeSeries.jl` package. It is very basic and does not have most (if not all) functions that you need, but it has an interface to add your own functions. In my needs those were all one-liners.

If you find yourself doing the same thing over and over again and feel that you are capable in Julia, consider trying it out and maybe pushing your changes to add to the package.

---

<div class="post-metadata">

**Author:** ![langestefan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/langestefan/32/207923_2.png) [@langestefan](https://discourse.julialang.org/u/langestefan)\
**Post date:** [May 15, 2026, 9:52am UTC](https://discourse.julialang.org/t/common-data-utilities-for-time-series/137104/11 "2026-05-15T09:52:24Z")

</div>

I tried it a while back, and I’m just not a fan, sorry. I don’t want to work with a special time-aware type, a time index column, or conversions between `TimeArray` and `DataFrame`. These should be simple operations directly on `Tables.jl` sources.

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [May 15, 2026, 10:00am UTC](https://discourse.julialang.org/t/common-data-utilities-for-time-series/137104/12 "2026-05-15T10:00:39Z")

</div>

I tried TimeSeries.jl in the past and liked it. The API isn’t ideal though, and I wish they had transforms like we did with GeoTables.jl.

Depending on the operations, it can be really painful to treat things as simple Tables.jl.

---

<div class="post-metadata">

**Author:** ![Boris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/boris/32/3306_2.png) [@Boris](https://discourse.julialang.org/u/Boris)\
**Post date:** [May 19, 2026, 5:01pm UTC](https://discourse.julialang.org/t/common-data-utilities-for-time-series/137104/13 "2026-05-19T17:01:46Z")

</div>

Fair enough.

I rely heavily exactly on these to generate helper matrices for my program, before I make all normal arrays for calculation.

---

<div class="post-metadata">

**Author:** ![kpa28](https://avatars.discourse-cdn.com/v4/letter/k/a9a28c/32.png) [@kpa28](https://discourse.julialang.org/u/kpa28)\
**Post date:** [May 23, 2026, 10:36pm UTC](https://discourse.julialang.org/t/common-data-utilities-for-time-series/137104/14 "2026-05-23T22:36:21Z")

</div>

If the tables you work with have fixed structure you could define structs for those column sets to use with StructArrays.jl. Then you can define `func(tbl::StructVector{<:MyTableType})`, then your table structures are in the type tree so you get good code reuse. If you have large numbers of columns or a large number of column subsets it won’t work of course.

I have a couple of unregistered packages, not promoting just including for illustration:

- [GitHub - kpa28-git/TimeBars.jl: Time series extensions for StructArrays.jl · GitHub](https://github.com/kpa28-git/TimeBars.jl)
- [GitHub - kpa28-git/MovingWindowsBase.jl: Implicit and TimeType-based moving window operations. · GitHub](https://github.com/kpa28-git/MovingWindowsBase.jl)

But if you truly want time series ops to be agnostic to any kind of table, I haven’t found that. Mwbase has some basic moving windows stuff, but it’s not intended for imputation.

TimeBars.jl mainly defines some abstract types / conventions I use. I used to have an impute method there (relying on Impute.jl), but I removed it as I don’t use it and I want the package to be minimal.

---

<div class="post-metadata">

**Author:** ![langestefan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/langestefan/32/207923_2.png) [@langestefan](https://discourse.julialang.org/u/langestefan)\
**Post date:** [May 23, 2026, 10:51pm UTC](https://discourse.julialang.org/t/common-data-utilities-for-time-series/137104/15 "2026-05-23T22:51:10Z")

</div>

> [@kpa28](#):
>
> Then you can define `func(tbl::StructVector{<:MyTableType})`, then your table structures are in the type tree so you get good code reuse.

Maybe I’m missing something here, but why would you want to dispatch on the table type? If your methods are compatible with the Tables.jl interface ([i.e. consuming Tables.jl-compatible sources](https://tables.juliadata.org/stable/using-the-interface/#Using-the-Interface-(i.e.-consuming-Tables.jl-compatible-sources))), you won’t have to care about the type of your table at all.

---

<div class="post-metadata">

**Author:** ![kpa28](https://avatars.discourse-cdn.com/v4/letter/k/a9a28c/32.png) [@kpa28](https://discourse.julialang.org/u/kpa28)\
**Post date:** [May 23, 2026, 11:03pm UTC](https://discourse.julialang.org/t/common-data-utilities-for-time-series/137104/16 "2026-05-23T23:03:20Z")

</div>

In general, you don’t need to. There were two reasons for my needs:

- I was fine with using StructArrays.jl for almost everything. StructVector is basically a columntable so you get the Tables interface for free
- I wanted methods that dispatched based on specific subsets of columns or the type of index. This kind of thing wouldn’t make sense for everyone, but if you know a lot about your tables in advance I’ve found this method useful.

Open to suggestions for a better way, but compared to the other time series packages this works better for my use cases. It’s not often that I have a large number of columns or unpredictable/changing sets of columns in table work.

EDIT: I wrote this a while ago to explain why I came to this way of doing things (kind of out of date though) - [TimeBars.jl/RATIONALE.md at master · kpa28-git/TimeBars.jl · GitHub](https://github.com/kpa28-git/TimeBars.jl/blob/master/RATIONALE.md)  
The README has some info about that as well.
