CSV 透视与逆透视
数据互转
正在载入
正在加载工具
工具代码会在打开时按需载入,请稍候。
本工具的全部运算都发生在你的浏览器中,输入内容不会发送到任何服务器。
关于这个工具
把交易明细转换为按地区和月份汇总的宽表,或把逐月宽表展开为包含标识符、变量名和值的长表。透视支持多个行键、一个列键、多个值列以及明确选择的聚合方式;逆透视保留所选标识列,并按原始解析字符串复制各值。重复的透视坐标会参与聚合,不会悄悄覆盖前一行。精确十进制运算避免二进制浮点误差;不符合格式的数值文本会报错,不能表示为有限小数的平均值则输出 1/3 等精确最简分数字符串,不会自行猜测或舍入。解析、转换和导出均在浏览器本地工作线程中完成。
常见用途
- 按地区和产品汇总销售明细,将月份展开为列,并对所选金额与数量列计算精确合计。
- 按原样分类键统计非空观测值,同时保留 001、1 以及区分大小写的部门代码。
- 把 Jan、Feb、Mar 列展开为变量名/值长表,供其他报表系统使用,同时保留账户编号、空单元格和原始小数写法。
使用方法
- 1.粘贴 CSV 文本或选择本地文件,设置分隔符、表头和支持的文件编码,再读取列信息。选择透视或逆透视。透视按需选择行键,再选择一个列键、一个或多个值列及聚合方式;这些角色不得重叠。逆透视选择要保留的标识列和要展开的值列,并设置变量名列与值列的输出名称。
- 2.运行前检查所选列。匹配键按原样字符串比较,不会自动去空白、忽略大小写或转为数字。数值聚合只接受说明中规定的十进制格式。逆透视默认保留空值与缺失值;只有确实要丢弃已存在的空字符串时,才选择丢弃空值。缺失的 null 值仍会保留。修改输入或设置会使此前结果失效。
- 3.执行转换,检查结果行列数和分页预览,再下载 JSON 或 CSV。分类值或原表头含有标点时,请查看输出列元数据。JSON 可区分 null 缺失值与空字符串,并保留字符串编号。供电子表格查看时建议启用 CSV 公式防护;只有确认目标可信时才显式选择原始 CSV。分页和缩短显示不会截断成功生成的完整导出。
透视与逆透视转换前后示例
按地区和产品透视精确销售合计
{
"input": "region,product,month,amount,units\nNorth,001,Jan,0.10,2\nNorth,001,Jan,0.20,3\nNorth,001,Feb,1.50,1\nSouth,001,Jan,4,2\nNorth,1,Jan,2,1",
"parseOptions": {
"delimiter": ",",
"header": true
},
"options": {
"mode": "pivot",
"rowKeys": [
"region",
"product"
],
"columnKey": "month",
"valueColumns": [
"amount",
"units"
],
"aggregation": "sum"
}
}{
"headers": [
"region",
"product",
"pivot:[\"Jan\",\"amount\",\"sum\"]",
"pivot:[\"Jan\",\"units\",\"sum\"]",
"pivot:[\"Feb\",\"amount\",\"sum\"]",
"pivot:[\"Feb\",\"units\",\"sum\"]"
],
"rows": [
[
"North",
"001",
"0.3",
"5",
"1.5",
"1"
],
[
"South",
"001",
"4",
"2",
null,
null
],
[
"North",
"1",
"2",
"1",
null,
null
]
]
}转换前的 North/001/Jan 出现两次,因此 0.10 + 0.20 得到精确字符串 0.3,2 + 3 得到 5。月份按首次出现顺序排列,每个月依次输出 amount 与 units。North/001 与 North/1 仍是不同分组;没有观测记录的地区/产品/月组合为 null。
计数非空值,包括文本
{
"input": "id,month,value\nA,Jan,yes\nA,Jan,\nA,Jan\nA,Feb,0\nB,Jan,",
"parseOptions": {
"delimiter": ",",
"header": true
},
"options": {
"mode": "pivot",
"rowKeys": [
"id"
],
"columnKey": "month",
"valueColumns": [
"value"
],
"aggregation": "count"
}
}{
"headers": [
"id",
"pivot:[\"Jan\",\"value\",\"count\"]",
"pivot:[\"Feb\",\"value\",\"count\"]"
],
"rows": [
[
"A",
"1",
"1"
],
[
"B",
"0",
null
]
]
}A/Jan 统计 yes,但跳过空字段与缺失字段;A/Feb 统计文本 0。B/Jan 有源坐标但没有非空观测,计数为 "0";B/Feb 没有源坐标,因此为 null。这既不是去重计数,也不是全部源行数。
计算精确的有限小数平均值
{
"input": "id,month,value\nA,Jan,0.1\nA,Jan,0.2\nB,Jan,0.125\nB,Jan,0.375",
"parseOptions": {
"delimiter": ",",
"header": true
},
"options": {
"mode": "pivot",
"rowKeys": [
"id"
],
"columnKey": "month",
"valueColumns": [
"value"
],
"aggregation": "avg"
}
}{
"headers": [
"id",
"pivot:[\"Jan\",\"value\",\"avg\"]"
],
"rows": [
[
"A",
"0.15"
],
[
"B",
"0.25"
]
]
}A 的 (0.1 + 0.2) / 2 精确等于 0.15;B 的 (0.125 + 0.375) / 2 精确等于 0.25。结果以十进制字符串输出,不引入二进制浮点近似。
从含负数的值中求最小值
{
"input": "id,month,value\nA,Jan,-3.20\nA,Jan,7.50\nA,Jan,-0.00",
"parseOptions": {
"delimiter": ",",
"header": true
},
"options": {
"mode": "pivot",
"rowKeys": [
"id"
],
"columnKey": "month",
"valueColumns": [
"value"
],
"aggregation": "min"
}
}{
"headers": [
"id",
"pivot:[\"Jan\",\"value\",\"min\"]"
],
"rows": [
[
"A",
"-3.2"
]
]
}-3.20、7.50 和 -0.00 的数值最小值为 -3.2。聚合会规范化小数写法,并按精确数值比较,不是按文本排序。
求超出 JavaScript 安全整数范围的最大值
{
"input": "id,month,value\nA,Jan,9007199254740992\nA,Jan,9007199254740993",
"parseOptions": {
"delimiter": ",",
"header": true
},
"options": {
"mode": "pivot",
"rowKeys": [
"id"
],
"columnKey": "month",
"valueColumns": [
"value"
],
"aggregation": "max"
}
}{
"headers": [
"id",
"pivot:[\"Jan\",\"value\",\"max\"]"
],
"rows": [
[
"A",
"9007199254740993"
]
]
}基于 BigInt 的比较仍能区分这两个大整数。精确最大值是字符串 9007199254740993,不会舍入为相邻的 JavaScript Number 可表示值。
以精确分数保留循环小数平均值
{
"input": "id,month,value\nA,Jan,1\nA,Jan,0\nA,Jan,0",
"parseOptions": {
"delimiter": ",",
"header": true
},
"options": {
"mode": "pivot",
"rowKeys": [
"id"
],
"columnKey": "month",
"valueColumns": [
"value"
],
"aggregation": "avg"
}
}{
"headers": [
"id",
"pivot:[\"Jan\",\"value\",\"avg\"]"
],
"rows": [
[
"A",
"1/3"
]
]
}此处平均值为 1/3,不能表示为有限小数。转换后保留精确最简分数字符串 "1/3",不舍入,也不转为二进制浮点数。需要保留该表示时请使用 JSON。分数结果不属于后续数值聚合可接受的十进制输入。
拒绝把前导零编号当成数值
{
"input": "id,month,value\nA,Jan,001",
"parseOptions": {
"delimiter": ",",
"header": true
},
"options": {
"mode": "pivot",
"rowKeys": [
"id"
],
"columnKey": "month",
"valueColumns": [
"value"
],
"aggregation": "sum"
}
}{
"error": "numeric"
}001 不符合数值求和规则,会返回 numeric,而不会变成 1。该文本仍可作为键、作为非空值计数,或由逆透视按原样复制。
逆透视前后保留原始值
{
"input": "id,Jan,Feb\n001,1.00,\n1,,null\n002,0\n003, ,=1+1",
"parseOptions": {
"delimiter": ",",
"header": true
},
"options": {
"mode": "unpivot",
"idColumns": [
"id"
],
"valueColumns": [
"Jan",
"Feb"
],
"variableName": "month",
"valueName": "amount",
"dropEmpty": false
}
}{
"headers": [
"id",
"month",
"amount"
],
"rows": [
[
"001",
"Jan",
"1.00"
],
[
"001",
"Feb",
""
],
[
"1",
"Jan",
""
],
[
"1",
"Feb",
"null"
],
[
"002",
"Jan",
"0"
],
[
"002",
"Feb",
null
],
[
"003",
"Jan",
" "
],
[
"003",
"Feb",
"=1+1"
]
]
}Jan 和 Feb 按源行顺序展开为 month 行。编号 001、小数写法 1.00、空字符串、文本 null、缺失的 Feb 值、空白及类似公式的文本均保留解析后的值。此处不会执行公式文本;受保护的 CSV 会改动风险字段,JSON 则原样保留。
逆透视时只丢弃现有空字符串
{
"input": "id,Jan,Feb\n001,1.00,\n1,,null\n002,0\n003, ,=1+1",
"parseOptions": {
"delimiter": ",",
"header": true
},
"options": {
"mode": "unpivot",
"idColumns": [
"id"
],
"valueColumns": [
"Jan",
"Feb"
],
"variableName": "month",
"valueName": "amount",
"dropEmpty": true
}
}{
"headers": [
"id",
"month",
"amount"
],
"rows": [
[
"001",
"Jan",
"1.00"
],
[
"1",
"Feb",
"null"
],
[
"002",
"Jan",
"0"
],
[
"002",
"Feb",
null
],
[
"003",
"Jan",
" "
],
[
"003",
"Feb",
"=1+1"
]
]
}仅移除 001 的空 Feb 与 1 的空 Jan。002 中不存在的 Feb 值仍保留为 null;空白和文本 null 也保留。这个显式选项不会悄悄抹去缺失观测。
区分空列键与缺失列键
{
"input": "id,month,value\nA,,1\nA\nB,Jan,2",
"parseOptions": {
"delimiter": ",",
"header": true
},
"options": {
"mode": "pivot",
"rowKeys": [
"id"
],
"columnKey": "month",
"valueColumns": [
"value"
],
"aggregation": "sum"
}
}{
"headers": [
"id",
"pivot:[\"\",\"value\",\"sum\"]",
"pivot:[null,\"value\",\"sum\"]",
"pivot:[\"Jan\",\"value\",\"sum\"]"
],
"rows": [
[
"A",
"1",
null,
null
],
[
"B",
null,
null,
"2"
]
]
}空的 month 字符串与不存在的 month 字段生成不同的透视列。A 的空分类合计为 1,而缺失分类的记录没有数值,因此该聚合为 null。B 只有 Jan。元数据以原样字符串或 null 记录各分类。
为与行键重名的生成表头消除冲突
{
"input": "\"pivot:[\"\"Jan\"\",\"\"amount\"\",\"\"sum\"\"]\",month,amount\n001,Jan,2",
"parseOptions": {
"delimiter": ",",
"header": true
},
"options": {
"mode": "pivot",
"rowKeys": [
"pivot:[\"Jan\",\"amount\",\"sum\"]"
],
"columnKey": "month",
"valueColumns": [
"amount"
],
"aggregation": "sum"
}
}{
"headers": [
"pivot:[\"Jan\",\"amount\",\"sum\"]",
"pivot:[\"Jan\",\"amount\",\"sum\"] [2]"
],
"rows": [
[
"001",
"2"
]
]
}原始行键表头本身就是 pivot:["Jan","amount","sum"],它保持不变;生成的聚合表头增加后缀 " [2]"。JSON 的 columns 元数据仍提供权威的源列、分类值和聚合方式映射。
透视无表头的分号分隔数据
{
"input": "001;Jan;0.1\n001;Jan;0.2",
"parseOptions": {
"delimiter": ";",
"header": false
},
"options": {
"mode": "pivot",
"rowKeys": [
"column1"
],
"columnKey": "column2",
"valueColumns": [
"column3"
],
"aggregation": "sum"
}
}{
"headers": [
"column1",
"pivot:[\"Jan\",\"column3\",\"sum\"]"
],
"rows": [
[
"001",
"0.3"
]
]
}header:false 表示首行是数据,位置列名为 column1、column2 和 column3。编号 001、月份 Jan 的两行合计为 0.3。分隔符通过设置明确指定,不猜测文件格式。
透视与逆透视常见误区
- 产品编号只在地区内唯一,却仅选择产品作为行键;应同时选择地区。
- 把所选值列的非空计数误认为源行数或去重后的值数量。
- 以为 001 与 1 是同一个键,或以为 CSV 能阻止电子表格自动推断类型。
- 把标识符列用于数值聚合,或期待科学计数法与本地化数字分隔符能自动识别。
- 把 1/3 等精确分数平均值误当成舍入小数,或直接当成另一次数值聚合可接受的十进制输入。
- 尚未确认缺失观测在目标系统中的意义,就丢弃空值。
- 以为聚合后的透视表可以无损恢复每条源记录。
- 在电子表格中打开不可信的原始 CSV,或未检查隐私信息就分享结果。
限制与说明
- 输入限制为 2 MiB 编码文件字节及 2 MiB 解码后 UTF-8 文本、10,000 条数据行、128 列,以及补齐缺失尾部字段后共 200,000 个单元格。输出限制为 50,000 行、含行键在内的 256 列、500,000 个单元格,JSON 与受公式防护的 CSV 各不得超过 12 MiB。不同的行键分组最多 10,000 个、列键分组最多 256 个;输出总列数可能先达到上限。在构造结果行之前,会检查行分组数 × 分类数 × 值列数带来的稠密增长。超限时阻止转换,不会静默截断。工作线程取消与请求超时用于限制执行,但不构成浏览器内存的硬隔离。
- 键与逆透视标识符始终是原样字符串:001 与 1、A 与 a、空字符串与缺失的 null 各不相同。不会去空白、忽略大小写、转换数字或日期、规范化 Unicode、模糊匹配或执行公式。复合键按元组识别。行键、列键和值列的角色不能重叠。不选行键时,所有记录归入一个行分组;不选逆透视标识列时,仅输出变量名与值两列。透视行与分类按首次出现顺序排列,值列保留选择顺序。逆透视按输入行顺序及所选值列顺序输出,不自动排序。
- 计数统计存在且非空的值,包括任意文本;它不是去重计数,也不是无条件统计源行数。数值聚合只跳过 null 与 "",要求完整字符串为可选负号、0 或非零开头的整数,后面可接小数点与小数数字。最多接受 100 个十进制数字和 50 位小数。空白、加号、科学计数法、分组分隔符、货币符号和前导零整数均被拒绝。BigInt 提供精确求和、最小值、最大值和平均值字符串,即使超过 JavaScript 安全整数范围也不会丢失精度。有限小数平均值使用规范化十进制字符串,循环小数平均值使用 1/3 等精确最简分数。十进制结果采用相同精度上限,分数的分子与分母分别限制为 100 位数字。小数末尾的零与负零会规范化;超出精度时整个转换失败。分数输出是字符串,不是后续数值聚合可接受的十进制输入。已有坐标但值全部为空时,计数为 "0",数值聚合为 null;输入中从未出现的坐标在任何聚合下均为 null。
- 透视表头以 pivot: 开头,后接由分类值、值列名和聚合方式组成的 JSON 元组。若与所选行键表头冲突,会添加 " [2]" 等确定性后缀;JSON 列元数据保留精确映射。请勿按猜测的标点拆解名称。逆透视默认保留缺失的 null、现有的 "" 以及文本 "null"。丢弃空值只移除已存在的空字符串;缺失字段、空白与单词 null 仍保留。输出的变量名列和值列名称不能为空,必须彼此不同,且不得与保留的标识列重名。聚合、数值输出规范化及丢弃空字符串会损失信息,逆透视无法从聚合结果重建原交易明细。
- 请明确选择逗号、分号、制表符或竖线,文件编码支持 UTF-8、UTF-16LE 或 UTF-16BE。编码无效或 BOM 不匹配时拒绝读取。表头不能为空,原样名称必须唯一;空白和大小写仍有意义。无表头时使用 column1、column2 等名称,由首条记录决定宽度。短行的缺失尾部值保留为 null;超宽记录或错误引号会被拒绝。每页预览 25 行、12 列,长名称和值会缩短;下载保留受限范围内的完整结果。JSON 保留结果字符串、null 和元数据,不保留原 CSV 字节。CSV 把 null 写为不带引号的空字段,把 "" 写为带引号的空字段,但普通读取器往往将二者合并。公式防护会添加英文单引号并改动风险表头/值;原始 CSV 可能触发公式,保存并重开后防护也未必有效。电子表格仍可能推断类型并改动编号。输入留在本地且不保存历史;下载可能暴露隐私,清空页面后文件仍会保留。
常见问题
同一个透视坐标出现多行时会怎样?
完整的行键元组、列键值和所选值列共同确定一个聚合单元格。请明确选择计数、求和、平均值、最小值或最大值。例如 0.1 与 0.2 的精确合计字符串为 0.3。工具不会悄悄保留首行或末行。若记录本应分别显示,请增加行键。
为什么金额被拒绝,或平均值显示为分数?
数值聚合采用严格格式,不会把带前导零的编号、含空白或加号的文本、科学计数法或超出支持精度的字符串猜成数字。请仅选择真正的数值列,或先清洗一份副本。(1 + 0 + 0) / 3 等平均值无法表示为有限小数,因此输出精确最简分数字符串 1/3,不会静默舍入。十进制结果及分数的组成部分均有明确精度上限。计数和逆透视可处理非数值文本,无需数值强制转换。
先透视再逆透视,能恢复原 CSV 吗?
通常不能。透视会合并重复坐标,可能规范化符合规则的数字写法,并为缺失组合创建单元格。逆透视可以把所选宽表单元格展开为长表,但无法恢复各笔交易、原始顺序或未保留的列。请保留原输入。JSON 保留的是转换结果的字符串、null 和列元数据,不是原文件的引号写法或字节。
空值、缺失值与文本 null 有什么不同?
已存在但长度为零的字段是空字符串;短记录末尾不存在的字段是缺失值;字符 null 只是普通文本。JSON 分别保留为 ""、null 与 "null"。逆透视默认保留三者;丢弃空值只移除已存在的零长度字符串,保留缺失的 null 字段。数值聚合跳过缺失值与空字符串,但把文本 null 判定为无效数字;计数则会统计这个非空文本。