npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-pivot-join

v0.1.0

Published

Table pipeline toolkit for DeepSeek Harness: join two CSV/JSON tables (inner/left/right/outer), build pivot tables, and run group-by aggregations with readable aligned output. Zero runtime dependencies, read-only.

Readme

dsh-pivot-join

DeepSeek Harness 的表格流水线工具:join_tables 按连接键合并两张表,pivot_table 把行转成透视表,group_aggregate 做分组统计。支持 CSV / JSON / JSONL 输入,输出对齐易读的表格。只读、零运行时依赖。

  • 源码:https://github.com/geeklei/dsh-plugins/tree/main/dsh-pivot-join
  • npm:https://www.npmjs.com/package/dsh-pivot-join

功能说明

对话里拿到的数据常是几张独立的 CSV:一张订单、一张客户、一张销量。要回答问题,往往先得把表拼起来、把行转成列、分组求和——这三个动作在终端里靠肉眼做非常费劲。本插件把它们变成三个工具。

join_tables —— 把两张表按连接键拼起来

支持 inner(交集)、left(保留左表全部)、right、outer(全外连接)四种方式,并给出匹配统计,能立刻看出「有多少行没有对上」:

来源:orders.csv × customers.csv
连接方式:inner,连接键:cust_id=id
左表:4 行 × 3 列;右表:3 行 × 3 列
结果:3 行 × 6 列(匹配 3,左未匹配 1,右未匹配 1)

| order_id | cust_id | amount |  id | name  | city |
| -------- | ------- | ------ | --- | ----- | ---- |
|     1001 |       1 |    120 |   1 | alice | 深圳 |
|     1002 |       2 |     80 |   2 | bob   | 北京 |
|     1003 |       1 |     60 |   1 | alice | 深圳 |

连接键可以是同名列(on="id")、不同名列(on="cust_id=id"),也可以是多列(on="region,quarter")。两侧同名的连接键只会保留一份,避免出现重复列。

pivot_table —— 把行转成列(透视表)

指定行维度、透视列、值列和聚合方式,直接得到一张交叉表:

来源:sales.csv
透视:index=region,columns=quarter,values=amount,agg=sum
源数据:6 行 × 5 列;分组 3 个,透视列取值 2 个

| region |  Q1 |  Q2 | 合计 |
| ------ | --- | --- | ---- |
| 华北   |  90 |  60 |  150 |
| 华东   | 200 | 150 |  350 |
| 华南   |   0 | 200 |  200 |

透视列的去重取值自动成为新列名,并附一列「合计」。不写 values 时按行数计数。

group_aggregate —— 分组统计

一条 aggs 清单可以同时算多个指标,amount:sum,qty:avg,count 表示「金额求和 + 数量求均值 + 行数」:

来源:sales.csv
分组:region;聚合:amount→sum, qty→avg, 行→count;排序:-value
源数据:6 行 × 5 列;分组数 3

| region | amount_sum | qty_avg | count |
| ------ | ---------- | ------- | ----- |
| 华东   |        350 |       3 |     3 |
| 华南   |        200 |       5 |     1 |
| 华北   |        150 |     1.5 |     2 |

结果默认按分组键升序,sort=-value 可按首个聚合值降序(上例即按金额从高到低)。

三种输入格式都会被自动识别:CSV(逗号 / 制表符 / 分号 / 竖线分隔均可)、JSON 对象数组、JSONL(每行一个对象)。CSV 还支持带引号的字段、字段内换行与双写引号转义。

安装

npm install dsh-pivot-join

安装后在 cordis.patch.yml 中加入:

- insert:
    - id: pivot-join
      name: "dsh-pivot-join"

使用说明

三个工具都支持 path(文件路径)或 text(内联文本)二选一,text 优先。CSV 字段默认去除首尾空白(trim 可关闭)。

join_tables

| 参数 | 类型 | 说明 | |---|---|---| | path_a / text_a | string | 左表(文件路径或内联文本) | | path_b / text_b | string | 右表(文件路径或内联文本) | | on | string | 连接键(必填):id 或 left_id=right_id;多键用逗号分隔 | | how | string | inner | left(默认) | right | outer(full 等同 outer) | | delimiter | string | CSV 分隔符,默认 auto 自动探测 | | trim | boolean | 是否去除字段首尾空白,默认 true | | limit | number | 结果预览行数,默认 20,上限 200 | | max_chars | number | 输出字符上限,默认 20000,上限 200000 | | max_rows | number | 单表读取行数上限,默认 100000,上限 1000000 | | max_size | number | 文件大小上限(KB),默认 10240,上限 51200 |

用户:订单表和客户表按客户 ID 关联一下

join_tables(path_a="orders.csv", path_b="customers.csv", on="cust_id=id", how="inner")

用户:看看哪些客户一单都没下

join_tables(path_a="customers.csv", path_b="orders.csv", on="id=cust_id", how="left")

pivot_table

| 参数 | 类型 | 说明 | |---|---|---| | path / text | string | 数据源(文件路径或内联文本) | | index | string | 行维度列,多列用逗号分隔,如 region,product | | columns | string | 透视列(必填),其去重取值会成为新列名 | | values | string | 被聚合的值列;留空则统计行数 | | agg | string | sum(默认) | avg | min | max | count | first | last;无 values 时默认 count | | delimiter / trim | — | 同 join_tables | | limit | number | 结果预览行数,默认 20,上限 200 | | max_chars / max_rows / max_size | number | 同上 |

用户:按区域和季度汇总一下销售额

pivot_table(path="sales.csv", index="region", columns="quarter", values="amount", agg="sum")

用户:看看每个区域的订单笔数分布

pivot_table(path="sales.csv", index="region", columns="quarter")

group_aggregate

| 参数 | 类型 | 说明 | |---|---|---| | path / text | string | 数据源(文件路径或内联文本) | | group_by | string | 分组列,多列用逗号分隔;留空表示对全表汇总 | | aggs | string | 聚合清单(必填),如 amount:sum,qty:avg,count | | sort | string | key(默认,分组键升序) | -key | value | -value | | delimiter / trim | — | 同 join_tables | | limit | number | 结果预览行数,默认 20,上限 200 | | max_chars / max_rows / max_size | number | 同上 |

aggs 写法:

  • 列名:聚合 —— 如 amount:sum,结果列名为 amount_sum
  • 裸 count 或 *:count —— 统计行数,结果列名为 count
  • 列名:count —— 统计该列的非空值个数

用户:按区域统计金额合计、数量均值和记录条数

group_aggregate(path="sales.csv", group_by="region", aggs="amount:sum,qty:avg,count", sort="-value")

用户:整张表一共多少条记录、金额合计多少

group_aggregate(path="sales.csv", aggs="amount:sum,count")

典型场景

  • 对账单核对:两张表 on="订单号" 做 outer 连接,一次看出双方各自多出的记录。
  • 补齐维度信息:订单表只有客户 ID,left 连接客户表拿到姓名与城市。
  • 交叉分析:pivot_table 把「区域 × 季度」展成矩阵,趋势一眼可见。
  • 指标汇总:group_aggregate 一条命令同时产出求和、均值、计数。
  • 数据质量核查:连接后的「左未匹配 / 右未匹配」数字即脏数据规模。
  • 全表盘点:group_by 留空即得到全表汇总行。
  • JSON 接口数据:直接把接口返回的 JSON 数组或 JSONL 丢进来,无需先转 CSV。
  • 口径抽查:limit=5 只看前几行,确认聚合口径无误后再放大。

安全边界

  • 只读:三个工具都不写入、不修改、不删除文件;测试含源文件 size/mtime 不变的只读性断言。
  • 不访问网络:全部处理在本地完成,无任何外部请求。
  • 不执行输入:纯文本解析,不做 eval、不加载模块、不执行单元格内容。
  • 二进制拒绝:读取时检测 NUL 字节,疑似二进制文件直接拒绝解析。
  • 多层上限:文件大小上限 51200 KB、读取行数上限 1000000、输出字符上限 200000、结果预览上限 200 行、透视列取值上限 50 个。超限即拒绝或截断并显式提示。
  • 不写临时文件:不落盘任何中间结果。
  • 不脱敏:字段值原样输出。若表中含密钥等敏感信息,请先用 dsh-credential-scan 检查再处理。

其他插件集成说明

| 协作插件 | 集成方式 | |---|---| | dsh-xml-toolkit | parse_xml(shape="json") 的结果可直接作为本插件的 JSON 输入 | | dsh-json-yaml-toolkit | 接口报文先转换 / 校验,再交给本插件做连接与聚合 | | dsh-csv-explorer | 先用 csv-explorer 预览列名与取值分布,确定连接键与透视列 | | dsh-chart-ascii | 把本插件输出的表格交给 chart-ascii 画成终端柱状图 / 折线图 | | dsh-file-search | 先定位工作区内相关 CSV 文件,再批量连接比对 | | dsh-fs-inspector | 事先查看文件体量,据此设置合适的 max_size / max_rows | | dsh-text-stats | 对原始字段做词频与体量统计,与结构化聚合互补 | | dsh-credential-scan | 处理前扫描表内是否混入凭据、密钥 |

版本说明

  • 0.1.0(2026-09-30):初始版本。
    • join_tables:inner / left / right / outer 四种连接;单列、多列与异名列名映射;同名键列自动去重;匹配 / 未匹配统计
    • pivot_table:行维度 + 透视列 + 值列聚合,自动展开列并附加合计列;透视列取值上限 50
    • group_aggregate:多指标聚合(sum/avg/min/max/count/first/last),支持按分组键或聚合值排序
    • 输入自动识别 CSV / JSON / JSONL;CSV 支持引号转义、字段内换行、CRLF、BOM 与 4 种分隔符探测
    • 中日韩字符按显示宽度对齐输出;二进制拒绝与多层上限保护

RoadMap

v0.2(计划)

  • join_tables 支持模糊键(去空格、忽略大小写、前缀匹配)与近似连接(按相似度找最接近的一行)
  • pivot_table 支持多值列与百分比 / 占比模式(行占比、列占比、总计占比)
  • group_aggregate 支持分位数(p50 / p90 / p99)与中位数
  • 输出格式选项:format=markdown|tsv|csv,便于把结果直接写回文件

v0.3(展望)

  • filter_rows:按条件表达式筛选后再连接 / 透视
  • union_tables:多表纵向合并并处理列不一致
  • 流式处理超大表(分块读取,突破整体载入内存的限制)
  • 表达式列(amount*qty:sum 形式的计算指标)

FAQ

Q:on 里写多列是什么规则? 逗号分隔,每项可以是 列名(两侧同名)或 左列=右列。也可以混用,如 on="region,month=mon"。

Q:为什么同名连接键在结果里只有一份,异名的却有两份? 同名键两份完全重复,去掉更易读;异名键(如 cust_id=id)保留双方,便于在 outer 场景下看出该行来自哪一侧。这是刻意设计。

Q:left 连接后没匹配上的行,右侧字段是什么? 空字符串。可用 how=outer 同时看到右侧未匹配的行。

Q:透视表中某个格子显示 0 或空白,是什么意思? 该组在该透视列取值下没有数据。sum / count 显示 0,avg / min / max 显示空白(无数据可平均)。

Q:透视列取值太多怎么办? 默认最多保留 50 个(按值排序取前 50),超出部分会在结果上方给出提示。建议先筛掉噪音列,或用多列 index 分组。

Q:count 和行数有什么区别? count(裸写或 *:count)统计行数;列名:count 统计该列非空值的个数。两者在有空值时会不同。

Q:数字列是怎么识别的? 渲染时若某列所有非空单元格都能转成数字,就按数值右对齐显示。聚合时无法转成数字的值会被忽略(count 除外)。

Q:中文列名、中文取值有问题吗? 没有。表头与取值都按 UTF-8 处理,输出会按显示宽度对齐中日韩字符。

Q:字段里本身带逗号怎么办? 用双引号包起来,例如 "深圳,南山";字段内的双引号写成两个双引号 "" 即可。

Q:能从 npm 的 lock 文件或 Excel 里直接读吗? package-lock.json 这类 JSON 可以直接读;.xlsx 不行,需要先导出为 CSV 或 JSON。

源码与发布地址

  • 源码:https://github.com/geeklei/dsh-plugins/tree/main/dsh-pivot-join
  • npm:https://www.npmjs.com/package/dsh-pivot-join

许可证

MIT