TsFileDataFrame 让你像操作 pandas DataFrame 一样读取一个或多个 TsFile 中的数值型测点数据, 无需关心底层文件格式与数据加载细节。它是 TsFile Python 包的一部分(pip install tsfile)。
from tsfile import TsFileDataFrame df = TsFileDataFrame("table_data/") # 加载目录下所有 .tsfile print(df) # 浏览所有序列(仅元数据) ts = df["weather.Beijing.humidity"] # 取一条序列(懒加载句柄) window = ts[20:100] # 按行号切片 -> np.ndarray data = df.loc[start:end, [ # 按时间戳对齐多条序列 "weather.Beijing.temperature", "weather.Beijing.humidity", ]] data.values # -> np.ndarray, shape (N, 2):N 个时间戳 × 2 条序列
TsFileDataFrame 围绕三个核心类型:
TsFileDataFrame:入口对象,加载一至多个 TsFile 并提供统一视图。初始化时只扫描元数据, 不读取实际数值。Timeseries:单条序列的懒加载句柄,通过 df[...] 获得。它携带序列元信息,但在按行号索引前 不读取任何数据。AlignedTimeseries:多条序列在同一时间轴上的对齐结果,通过 df.loc[...] 获得,会一次性将 指定时间范围内的数据读入内存:对齐后的时间戳数组(.timestamps,长度 N)以及值矩阵 (.values,形状 (N, M))——N 行时间戳 × M 列序列。下表中 df 是一个 TsFileDataFrame 实例,由 df = TsFileDataFrame(paths) 创建。
| 示例 | 操作 | 返回类型 |
|---|---|---|
TsFileDataFrame(paths) | 加载文件 / 文件列表 / 目录 | TsFileDataFrame |
len(df) | 时间序列总数 | int |
df.list_timeseries("weather") | 获取序列名,可按前缀筛选 | List[str] |
df["weather.Beijing.humidity"]、df[0]、df[-1] | 获取单条序列 | Timeseries |
df["city"] | 获取某元数据列(标签 / field / start_time / end_time / count) | pandas.Series |
df[0:3]、df[[0, 2, 5]] | 按整数位置取子集视图:连续区间(0:3)或所列位置([0, 2, 5]);位置即打印的 index 列 | TsFileDataFrame |
df[df["city"] == "Beijing"] | 按元数据列过滤 | TsFileDataFrame |
df.loc[start:end, series_list] | 按时间戳对齐查询 | AlignedTimeseries |
df.show(max_rows=20) / print(df) | 打印元数据表格 | — |
df.close() | 释放文件句柄 | — |
下表中 ts 是一条 Timeseries,由 ts = df[...] 获得。
| 示例 | 操作 | 返回类型 |
|---|---|---|
ts.name | 序列名 | str |
len(ts) | 序列点数 | int |
ts.stats | 序列统计信息 | dict(start_time、end_time、count) |
ts[20] | 单值读取 | float(空值为 None) |
ts[20:100] | 行范围切片 | np.ndarray |
ts.timestamps | 时间戳数组 | np.ndarray |
下表中 data 是一个 AlignedTimeseries,由 data = df.loc[...] 获得。
| 示例 | 操作 | 返回类型 |
|---|---|---|
data.shape | 形状 (N, M)——N 为时间戳数,M 为序列数 | tuple |
data.timestamps | 时间戳数组 | np.ndarray |
data.values | 值矩阵 | np.ndarray,shape (N, M) |
data.series_names | 序列名列表 | List[str] |
len(data) | 行数 | int |
data[0]、data[0:10]、data[0, 1] | 行 / 元素索引 | np.ndarray / 标量 |
data.show(50) / print(data) | 格式化输出(自动截断) | — |
TsFileDataFrame 以序列名(一个字符串)作为序列的唯一标识。序列名由 表名、各标签列的取值、 字段名 三部分按此顺序经 . 连接构成:
{表名}.{标签值1}.{标签值2}...{字段名}
list_timeseries() 返回 SeriesPath 对象——str 的子类,其字符串值即上面的转义路径,可直接用作 df[...]、df.loc[...] 的键;它还以 .table、.tags(元组,None 表示空标签)、.field 暴露各组成部分。
示例:
weather.Beijing.humidity — 表 weather,标签 Beijing,字段 humiditysensor.s1.pressure — 表 sensor,标签 s1,字段 pressure名称中的转义。 . 用作分隔符,因此属于表名/标签/字段名本身的 . 会用反斜杠转义;空标签值写作 \N(与字面字符串 "null" 区分)。list_timeseries() 返回的就是这种转义形式——例如表 weather 中标签值 Bei.jing、字段 humidity 渲染为 weather.Bei\.jing.humidity(字面 \ 转义为 \\)。选取时也要用这种转义形式:可直接复用 list_timeseries() 返回的 SeriesPath(或读取它的 .table/.tags/.field),或用 raw string 保留反斜杠:
df[r"weather.Bei\.jing.humidity"] # 标签 "Bei.jing"(点号是值的一部分) df[r"weather.\N.Beijing.humidity"] # 标签 (null, "Beijing")
序列名可由
list_timeseries()获取,无需手工构造;亦可改用整数索引(df[0])或元数据过滤 (df[df["city"] == "Beijing"])选择序列。
路径可以是单个文件、目录,或由文件与目录混合组成的列表:
from tsfile import TsFileDataFrame df = TsFileDataFrame(["data/weather.tsfile", "data/sensor.tsfile"]) df = TsFileDataFrame("data/") # 递归查找目录下所有 .tsfile print(df)
初始化时只扫描元数据,不读取实际数值。加载多个文件时,会并行扫描元数据,使用 min(文件数, CPU 核数) 个线程;单个文件则串行扫描。
只有数值型 field(字段) 列承载可读数据(BOOLEAN、INT32、INT64、FLOAT、DOUBLE、TIMESTAMP);非数值字段(STRING、TEXT、BLOB、DATE)在加载时被跳过,不会成为序列。tag(标签) 列不受此限——字符串标签作为设备标识与元数据(序列名、df["city"] 列、元数据过滤)是完全支持的。
如果多个文件包含 同名序列(如按日分片的 weather.Beijing.humidity),会自动合并为一条连续序列。 各分片的时间戳不能冲突(不可重复),否则读取该序列时会报错。请在预处理阶段去重。
print(df)(以及 df.show(max_rows=...))打印序列元信息,数据量大时头尾截断。表头为:
index │ table │ <tag1> │ <tag2> │ ... │ field │ start_time │ end_time │ count
表头的标签列是所有表 tag 列名的并集(按首次出现顺序排列)。每行只填本表拥有的 tag 列,其余留空;仅当标签值本身为空时才显示 None。
TsFileDataFrame(table model, 972 time series, 5 files) table ps_id sn frac field start_time end_time count 0 pvf 10 30100194A00234H00572 1 pac 2024-04-02 00:00:00 2024-10-28 23:45:00 20160 1 pvf 10 30100194A00234H00572 1 tenmeterswindspeed 2024-04-02 00:00:00 2024-10-28 23:45:00 20160 ...
list_timeseries(path_prefix="") 列出已加载文件中的序列名,可按前缀筛选;不传参返回全部序列。
>>> df.list_timeseries("weather") ['weather.Beijing.humidity', 'weather.Beijing.temperature', 'weather.Shanghai.humidity', 'weather.Shanghai.temperature'] >>> df.list_timeseries("weather.Beijing") ['weather.Beijing.humidity', 'weather.Beijing.temperature']
若需查看起止时间、点数等元信息,可打印 DataFrame(或其子集)——见DataFrame 的展示。
df[...] 返回懒加载的 Timeseries 句柄(不触发读取),或返回子集视图:
ts = df["weather.Beijing.humidity"] # 按名称 ts = df[0] # 按索引(支持负索引) sub_df = df[0:3] # 切片 -> TsFileDataFrame(视图) sub_df = df[[0, 2, 5]] # 整数列表 -> TsFileDataFrame(视图) sub_df = df[df["city"] == "Beijing"] # 按元数据过滤 -> TsFileDataFrame(视图)
>>> df["weather.Beijing.humidity"] Timeseries('weather.Beijing.humidity', count=2880, start=2026-01-27 00:00:00, end=2026-02-05 23:55:00)
序列元信息从缓存读取(无 I/O):
>>> ts = df["weather.Beijing.humidity"] >>> ts.name 'weather.Beijing.humidity' >>> len(ts) 2880 >>> ts.stats {'start_time': 1769443200000, 'end_time': 1770306900000, 'count': 2880}
对 Timeseries 按行号索引时才触发实际的文件读取:
val = ts[20] # -> float window = ts[20:100] # -> np.ndarray, shape = (80,) last_ten = ts[-10:] # -> np.ndarray sampled = ts[::2] # -> np.ndarray(步长采样) ts.timestamps[20:100] # -> 对应行号的时间戳, np.ndarray
>>> ts[20] 46.1 >>> ts[20:100] array([46.1 , 41.72, 52.94, ..., 76.3 , 84.35]) >>> ts.timestamps[20:100] array([1769449200000, 1769449500000, ..., 1769472900000])
当需要多条序列在同一时间轴上严格对齐时,使用 .loc:
data = df.loc[start_time:end_time, [ "weather.Beijing.humidity", "weather.Beijing.temperature", "sensor.s1.pressure", ]]
返回的 AlignedTimeseries 将所有序列对齐到时间戳的 并集,缺失位置填充 NaN:
data.timestamps # np.ndarray,毫秒时间戳 data.values # np.ndarray, shape = (N, 3) data.series_names # ["weather.Beijing.humidity", ...] data.shape # (N, 3) data[0:10] # 前 10 行, np.ndarray shape = (10, 3) data.show(50) # 最多显示 50 行
序列可按名称或索引指定,并可混用:
df.loc[start_time:end_time, [0, 1, 4]] df.loc[start_time:end_time, [0, "weather.Beijing.temperature", 4]]
>>> df.loc[1769616000000:1769702100000, ... ['weather.Beijing.temperature', 'weather.Beijing.humidity', 'sensor.s2.pressure']] AlignedTimeseries(288 rows, 3 series) timestamp weather.Beijing.temperature weather.Beijing.humidity sensor.s2.pressure 2026-01-29 00:00:00 29.12 92.87 NaN 2026-01-29 00:05:00 1.55 87.34 NaN ...
打印结果会在值列左侧显示时间列,但 .values 矩阵只含值列——对齐后的时间戳请用 df.loc[...].timestamps 读取。
with 语句会自动释放文件句柄,也可以手动关闭:
with TsFileDataFrame("data/") as df: ... # 退出后自动关闭 tsdf = TsFileDataFrame("data/") tsdf.close() # 也可以自己关闭