Datasets documentation

加载 TsFile 数据

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

加载 TsFile 数据

TsFile 是一种专为时间序列数据设计的列式文件格式,用作 Apache IoTDB 的原生存储层。与 Parquet 等通用列式格式相比,TsFile 感知时间序列数据模型(时间戳、设备和测量值),并维护一个内部时间索引,从而支持在不扫描整个文件的情况下进行时间范围裁剪。

由于该加载器不遵循常规的“每行一条记录”的表格约定,因此我们将其作为单独的指南提供:每个输出行对应一个 device,而每次测量的值则以 Arrow list<...> 列的形式返回。具体映射关系将在下文详细说明。

安装

加载器依赖于 tsfile Python 包:

pip install "tsfile>=2.3.0"

数据模型和输出布局

加载器遵循 TsFile 的 表模型。每个表的列是以下之一:

  • TAG — a string-typed identifier; the tuple of TAG values uniquely identifies a device (i.e. a single time-series source).
  • FIELD — 值随时间演化的测量值。
  • TIME — 时间戳列,默认命名为 time。

加载器为每个设备输出一行数据集。在每一行中,time 列和所有 FIELD 列均为 Arrow list<...> 列,包含该设备的完整时间序列,并按时间升序排列。TAG 列则显示为标量 string 列。

具体来说,输出模式的形式为:

<tag_1>:    string
<tag_2>:    string                       # one column per TAG
...
time:       list<timestamp[unit, tz]>
<field_1>:  list<original_type>          # one column per FIELD
<field_2>:  list<original_type>
...

当同一设备出现在拆分(split)的多个输入文件中时,其按文件划分的分块(chunks)会先按时间戳排序并拼接,然后作为单行输出。同一设备出现重复时间戳时会引发 ValueError。

基本用法

加载单个 TsFile:

>>> from datasets import load_dataset
>>> dataset = load_dataset("tsfile", data_files="my_data.tsfile")

显式地将文件映射到拆分:

>>> dataset = load_dataset(
...     "tsfile",
...     data_files={"train": "train_data.tsfile", "test": "test_data.tsfile"},
... )

Hub 上的示例数据集

在 tsfile/lotsa_data 中提供了一个可直接使用的示例。由于 .tsfile 文件会被自动识别,因此您可以直接通过仓库 ID 加载它,而无需指定 data_files:

>>> from datasets import load_dataset
>>> dataset = load_dataset("tsfile/lotsa_data")
>>> dataset
DatasetDict({
    train: Dataset({
        features: ['timeseries_id', 'time', 'value'],
        num_rows: 91
    })
})

每一行代表一个设备。timeseries_id 列中的 TAG 用于标识设备,而 time 和 value 是 list<...> 列,保存该设备的完整时间序列:

>>> row = dataset["train"][0]
>>> row["timeseries_id"]
'Bear_assembly_Angel'
>>> len(row["time"]), len(row["value"])
(8760, 8760)
>>> row["time"][:3]
[datetime.datetime(2017, 1, 1, 0, 0), datetime.datetime(2017, 1, 1, 1, 0), datetime.datetime(2017, 1, 1, 2, 0)]

选择表格

TsFile 可以包含多个表。当省略 table_name 时,将使用第一个有效文件中找到的第一个表。查找操作不区分大小写。

>>> dataset = load_dataset("tsfile", data_files="my_data.tsfile", table_name="sensor_data")

选择列

columns 限制所读取的 FIELD 列。TAG 列和 time 列始终会返回,因为它们用于标识设备及其时间线。columns 中指向 TAG 或 time 列的名称会被静默忽略(它们仍会照常输出,仅一次);与所有文件中均不存在的字段相匹配的名称将变为全为 null 的列表列。

>>> dataset = load_dataset(
...     "tsfile",
...     data_files="my_data.tsfile",
...     columns=["temperature", "humidity"],
... )

按时间范围筛选

start_time 和 end_time 为包含边界;两者均可省略。这些边界会下推至 TsFile 的内部时间索引,因此仅从磁盘读取匹配的数据块。两个边界均接受以下任意一种:

  • int — timestamp_unit 中的原始纪元(默认单位为毫秒);
  • datetime.datetime — 无时区信息的值被视为 UTC,带时区信息的值会被转换为 UTC;
  • datetime.date;
  • ISO-8601 str,例如 "2024-01-01T00:00:00";
  • pyarrow.TimestampScalar.
>>> from datetime import datetime
>>> dataset = load_dataset(
...     "tsfile",
...     data_files="my_data.tsfile",
...     start_time=datetime(2023, 11, 14),
...     end_time="2023-11-15T00:00:00",
... )

跨文件的模式演进

当不同文件暴露不同的列时——例如后续引入了新的传感器字段——加载器会取所有 FIELD 列的并集,并用 null 填充缺失值。数值型 FIELD 类型将按照 IoTDB 的加宽规则进行提升(INT32 → INT64 → DOUBLE、INT32 → FLOAT → DOUBLE)。

>>> dataset = load_dataset("tsfile", data_files=["day1.tsfile", "day2.tsfile"])

处理无法读取的文件

默认情况下,无法读取或非 TsFile 的输入会引发错误。将 on_bad_files 设置为 "warn" 以记录日志并继续,或设置为 "skip" 以静默丢弃该文件。

>>> dataset = load_dataset("tsfile", data_files="data/*.tsfile", on_bad_files="skip")

时间戳单位和时区

timestamp_unit(默认值为 "ms",与 IoTDB 保持一致)控制 time 列的分辨率以及整数时间边界的解释方式。timestamp_tz 为 Arrow 时间戳类型附加时区;None(默认值)将生成无时区类型。

>>> dataset = load_dataset(
...     "tsfile",
...     data_files="my_data.tsfile",
...     timestamp_unit="us",
...     timestamp_tz="UTC",
... )

内存与批处理

两个参数控制内存使用:

  • input_batch_size(默认值 65_536)—— 从 TsFileReader.query_table 中每个 Arrow 批次获取的最大行数。用于在流式处理单个设备时限制峰值内存。
  • output_batch_size(默认值为 32)— 提供给写入器的每个 Arrow 记录批次中包含的设备数量。较小的值可提供更及时的进度报告;较大的值可降低每个批次的开销。
>>> dataset = load_dataset(
...     "tsfile",
...     data_files="large_data.tsfile",
...     input_batch_size=32_768,
...     output_batch_size=128,
... )

峰值内存受单个设备在拆分中承载的数据量限制,而非受整个拆分的规模限制。

有关完整参数列表,请参阅 TsFileConfig。

Update on GitHub