mcpField
X
xolars

xolars

github.com/d-laub数据与数据库068 次安装18 周前更新
代码仓库

关于 xolars

xolars 是将 xarray.Dataset 与按维度组织的 Polars 数据框对齐的不可变容器,适用于需要同时管理多维数据集和维度元数据的 Python 用户。它支持惰性或即时数据框,并提供选择、赋值、合并及磁盘往返操作。

主要功能

  1. 01按维度关联 Polars 数据框
  2. 02校验坐标集合并自动对齐行序
  3. 03支持 DataFrame 与 LazyFrame
  4. 04按位置或标签同步选择
  5. 05赋值与合并时保持固定坐标
  6. 06通过 Zarr 和 Parquet 读写

适用场景

  1. 01为 xarray 维度附加 Polars 元数据
  2. 02按索引或坐标筛选数据及关联框架
  3. 03在数据集中分配或合并变量
  4. 04将数据写入磁盘后重新打开

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/d-laub/xolars --skill xolars

安装后在 Claude Code 中输入/xolars确认已加载。

详细介绍

xolars 公共 API

xolars 是一个小型的冻结容器:由一个 xarray.Dataset 和每个维度对应的一个 Polars 框架组成,并在选择和磁盘往返过程中保持与 Dataset 坐标顺序对齐。

公共接口

import xolars 仅公开一个名称:

  • xolars.Xolars — 容器

使用 from xolars import Xolars。xolars._core 下的内容都是内部实现。

Xolars 使用 attrs 冻结,并且是 Generic[F],其中 F = pl.DataFrame | pl.LazyFrame ——每个维度对应的框架类型都相同。它是冻结的,因此 isel/sel/collect 会返回新实例;它们不会修改原实例。

构造

from xolars import Xolars

xo = Xolars(ds=dataset, df={"sample": sample_frame, "gene": gene_frame})
# positional also works: Xolars(dataset, {"sample": sample_frame})
  • ds: xr.Dataset
  • df: Mapping[Hashable, pl.DataFrame | pl.LazyFrame] — 一个以维度名称为键的字典,每个需要元数据的维度对应一个框架(不必包含每个维度)。它不是单个框架,也不是列表。
构造时强制执行的不变量(每项不满足时都会引发 ValueError)

对于每个 dim -> frame:

  1. dim 必须是 ds 的实际维度。
  2. frame 必须包含一个名称恰好为 dim 的列(连接键)。
  3. 该列的值必须与 ds[dim] 坐标构成的集合相同——长度相同,成员相同。缺少或多出的 ID 都会引发错误;部分重叠也会引发错误。

行顺序无关紧要:框架会自动重排(通过对 dim 列执行右连接),使其与 Dataset 的坐标顺序一致。不要预先排序。

选择 — isel / sel

签名与 xarray.Dataset.isel / .sel 相同(索引器字典或关键字参数、 drop、missing_dims;sel 还接受 method/tolerance):

xo.isel(sample=slice(0, 10))      # positional
xo.sel(sample=["S1", "S2"])       # label-based

两者都会对子集化 Dataset,并且筛选每个索引维度对应的框架,以保持框架对齐。会丢弃维度的标量索引器也会丢弃该维度对应的框架。未被索引的维度对应的框架保持不变。

若要按元数据筛选(例如 age > 50),请自行筛选框架以获取 ID,然后将这些 ID 传给 sel——Xolars 没有元数据谓词方法:

frame = xo.df["sample"]                       # may be DataFrame or LazyFrame
ids = frame.filter(pl.col("age") > 50).select("sample")
ids = ids.collect() if isinstance(ids, pl.LazyFrame) else ids
xo2 = xo.sel(sample=ids["sample"].to_list())

添加数据 — assign / merge

两者都是函数式操作(返回一个新的 Xolars);一维数据存放在对应维度的 Polars 框架中,多维数据存放在 Dataset 中。

# assign one or more named variables (xarray.Dataset.assign idiom)
xo2 = xo.assign(gc=("gene_id", gc_array))                 # 1-D -> gene_id frame
xo2 = xo.assign(counts=(("gene_id", "sample_id"), mat))   # 2-D -> Dataset
xo2 = xo.assign(score=some_named_dataarray)               # aligned by label
# passing an xarray.Dataset value is an error -> use merge()

# merge whole objects; 1-D vars in xarray objects move to Polars
xo2 = xo.merge(other_dataset, gene_frame)                 # bare frame: dim inferred
xo2 = xo.merge(frames={"gene_id": [f1, f2]})              # explicit, aligned to gene_id

名称冲突时会静默覆盖。Polars/xarray 输入会与固定坐标左对齐(子集 → null,多出的部分 → 丢弃);现有 ds 坐标集合不会扩展(但 ≥2 维变量可以引入新维度)。

磁盘往返 — write / open

xo.write(path, mode="w")          # mode is REQUIRED (a zarr write mode)
reopened = Xolars.open(path)      # classmethod -> Xolars[pl.LazyFrame]
  • write(path, mode) 会创建 path/,其中包含 dataset.zarr/,以及每个框架对应的一个 {dim}.parquet。mode 没有默认值——请传入 "w"(覆盖)、"w-"、"a" 等(xarray ZarrWriteModes)。
  • open(path) 会读取 dataset.zarr,并对其旁边的每个 *.parquet 执行 scan_parquet——返回的框架为惰性(pl.LazyFrame)。
  • 两个 path 参数的类型都是 pathlib.Path;请传入 Path,而不是普通字符串。

惰性与急切 — collect

open 会返回 LazyFrame。若要将每个框架都物化为 pl.DataFrame:

eager = reopened.collect()        # -> Xolars[pl.DataFrame]

构造、验证和选择都支持这两种类型,因此只有在确实需要急切框架时才调用 collect()。

常见错误

错误修正
Xolars(dataset, metadata=df)Xolars(ds=dataset, df={dim: frame})
将单个普通框架或列表作为 df 传入df 是一个以维度名称为键的字典
框架缺少以维度命名的列添加名称恰好为 dim 的列;它是连接键
框架 ID 与 ds[dim] 只有部分重叠必须构成相同的集合(长度和成员都相同),否则会引发错误
预先排序框架行以匹配坐标无需这样做——构造时会自动重排
xo.to_zarr(...) / Xolars.open_zarr(...)xo.write(path, mode) / Xolars.open(path)
xo.write(path)必须提供 mode,例如 mode="w"
期待 open 返回急切框架返回的是 LazyFrame;请调用 .collect()

评论

支持 Markdown