timeseries-expand
English
timeseries-expand expands low-frequency time series into high-frequency series with publication-aware forward fill - every published value carries forward until the next publication, rather than being interpolated or back-filled.
Built for real-world data: weekly releases shifted by holidays, monthly indicators with occasional gaps, annual statistics that need daily granularity for downstream models.
Why?
Most off-the-shelf resamplers assume strict periodicity. Real publishing schedules aren't like that:
- A weekly coal price index published on Monday - except when Monday is a public holiday, when it's pushed to Tuesday or Wednesday.
- A monthly indicator with the occasional skipped release.
- An annual figure that downstream code needs at hourly granularity.
timeseries-expand handles these cases explicitly and flags gaps so you can audit them later.
Supported frequency ladder
Any source frequency can be expanded to any higher (finer) target frequency.
| Source / Target | Yearly | Quarterly | Monthly | Semi-Month | Weekly | Daily | Hourly |
|---|---|---|---|---|---|---|---|
| Yearly | - | Y | Y | Y | Y | Y | Y |
| Quarterly | - | - | Y | Y | Y | Y | Y |
| Monthly | - | - | - | Y | Y | Y | Y |
| Semi-Month | - | - | - | - | Y | Y | Y |
| Weekly | - | - | - | - | - | Y | Y |
| Daily | - | - | - | - | - | - | Y |
| Hourly | - | - | - | - | - | - | - |
21 supported combinations.
Install
pip install timeseries-expand
Quick start
import pandas as pd
from timeseries_expand import expand
# Weekly coal price index, published roughly every Monday
df = pd.DataFrame({
"timestamp": pd.to_datetime([
"2024-01-08", "2024-01-15", "2024-01-22",
"2024-01-29", "2024-02-12",
]),
"value": [101.5, 102.3, 103.1, 102.8, 104.2],
})
result = expand(df, source_freq="W-MON", target_freq="h")
print(result.head())
Features
- Publication-aware forward fill - semantics
[T, T_next)(carries forward until the next release) - Gap detection - flags intervals exceeding 1.5x expected cadence with
gap_flagcolumn - DST-safe - internal UTC, configurable display timezone
- 21 frequency combinations - expand yearly/quarterly/monthly/weekly/daily data
- 173 tests - pytest + Hypothesis property-based tests
- 3 call patterns - functional API, class-based API, CLI
Custom output date format
Pass date_format to format output timestamps as strings using any
pandas strftime pattern:
# Functional API
result = expand(df, "W-MON", "h", date_format="%Y-%m-%d %H:%M")
# Result: "2024-01-01 00:00"
result = expand(df, "ME", "D", date_format="%Y-%m")
# Result: "2024-01" (year-month only)
result = expand(df, "W-MON", "D", date_format="%Y W%W")
# Result: "2024 W01" (ISO week)
CLI:
ts-expand in.csv out.csv --source-freq W-MON --target-freq h \
--date-format "%Y-%m-%d"
Common placeholders (pandas supports a subset of strftime):
| code | meaning | example |
|---|---|---|
%Y |
4-digit year | 2024 |
%m |
month (01-12) | 01 |
%d |
day of month (01-31) | 15 |
%H:%M |
hour:minute | 09:30 |
%a |
weekday abbr | Mon |
%b |
month abbr | Jan |
%j |
day of year (001-366) | 035 |
%W |
ISO week number (00-53) | 05 |
%z |
UTC offset | +0800 |
Omit date_format (default None) to keep output as Timestamp objects.
Custom output time range
Clip the output to a subset of the input range with start / end:
# Functional API
result = expand(df, "W-MON", "h", start="2024-03-01", end="2024-06-30")
# Output: 2024-03-01 to 2024-06-30 (clipped, no extrapolation)
result = expand(df, "W-MON", "h", start="2024-12-01")
# Only start: goes from 2024-12-01 to the input's last date
CLI:
ts-expand in.csv out.csv --source-freq W-MON --target-freq h \
--start 2024-03-01 --end 2024-06-30
Rules:
start/endmust lie within the input data range; otherwiseValueError.start > endraisesValueErrorat config construction.- Accepts ISO date strings,
pd.Timestamp, ordatetime.date. Naive values are assumed UTC. - Combine with
date_formatfor formatted output:expand(df, "W-MON", "h", start="...", date_format="%Y-%m-%d").
CLI
ts-expand input.csv output.csv --source-freq W-MON --target-freq h
ts-expand --version
Contributing
See CONTRIBUTING.md.
License
MIT - see LICENSE.
中文
timeseries-expand 用"按发布时点的前向填充"语义,将低频时间序列扩充到高频 - 每个发布值沿用至下一次发布。
为真实场景设计:被节假日推迟的周度发布、偶尔缺失的月度指标、需要小时级粒度的年度统计数据。
支持的频率阶梯
任意源频率可扩充到任意更高的目标频率。共支持 21 种组合。
| 源 / 目标 | 年度 | 季度 | 月度 | 半月 | 周度 | 日度 | 小时 |
|---|---|---|---|---|---|---|---|
| 年度 | - | Y | Y | Y | Y | Y | Y |
| 季度 | - | - | Y | Y | Y | Y | Y |
| 月度 | - | - | - | Y | Y | Y | Y |
| 半月 | - | - | - | - | Y | Y | Y |
| 周度 | - | - | - | - | - | Y | Y |
| 日度 | - | - | - | - | - | - | Y |
| 小时 | - | - | - | - | - | - | - |
安装
pip install timeseries-expand
快速上手
import pandas as pd
from timeseries_expand import expand
df = pd.DataFrame({
"timestamp": pd.to_datetime([
"2024-01-08", "2024-01-15", "2024-01-22",
"2024-01-29", "2024-02-12",
]),
"value": [101.5, 102.3, 103.1, 102.8, 104.2],
})
result = expand(df, source_freq="W-MON", target_freq="h")
print(result.head())
核心特性
- 按发布时点的前向填充 - 语义
[T, T_next),沿用至下一次发布 - 间隙检测 - 默认 1.5 倍期望周期以上的间隔自动标记
gap_flag - DST 安全 - 内部 UTC,可配置显示时区
- 21 种频率组合 - 年级/季度/月度/半月/周度/日度数据任意扩充
- 173 个测试 - pytest + Hypothesis 属性测试
- 3 种调用方式 - 函数式 API、类 API、CLI
自定义输出时间范围
使用 start / end 把输出裁剪到输入的子区间:
result = expand(df, "W-MON", "h", start="2024-03-01", end="2024-06-30")
# 输出:2024-03-01 到 2024-06-30(裁剪,不外推)
result = expand(df, "W-MON", "h", start="2024-12-01")
# 只给 start:从 2024-12-01 到输入的最后一个日期
CLI:
ts-expand in.csv out.csv --source-freq W-MON --target-freq h \
--start 2024-03-01 --end 2024-06-30
规则:
start/end必须落在输入数据范围内,否则抛ValueError。start > end在配置构造时就抛ValueError。- 接受 ISO 日期字符串、
pd.Timestamp或datetime.date,naive 值假定为 UTC。 - 可与
date_format组合:expand(df, "W-MON", "h", start="...", date_format="%Y-%m-%d")。
命令行
ts-expand input.csv output.csv --source-freq W-MON --target-freq h
ts-expand --version
文档
GitHub: https://github.com/Lance-Chen/timeseries-expand
PyPI: https://pypi.org/project/timeseries-expand/
Metadata
Release files for timeseries-expand 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| timeseries_expand-0.2.0.tar.gz | 5.6 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| timeseries_expand-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 5.6 MB
Release files / timeseries_expand-0.2.0.tar.gz
| Download URL | timeseries_expand-0.2.0.tar.gz |
|---|---|
| Size | 5.6 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d2ca7f2cb14ca152461ad05387293befa797585d04a3f8418dfcf452a4e15ba1
|
|
BLAKE2b-256 checksum How to use checksums |
c7847d9e205d22b1d639a2d876672c0a1422342bb666f52a419db9a54b29bf42
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 15, 2026.
Transparency logRelease files / timeseries_expand-0.2.0-py3-none-any.whl
| Download URL | timeseries_expand-0.2.0-py3-none-any.whl |
|---|---|
| Size | 11.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b5df957700987e2c93de74e8ff3642662028a5fcb371bca67a857bf49df452bc
|
|
BLAKE2b-256 checksum How to use checksums |
811aa5a2499f210556b6a24f7e911557851c2235a75f6d67389d170d932fbd41
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 15, 2026.
Transparency log