数据结构:长数据 vs 宽数据
先把结论放前面:宽数据更适合人眼阅读,长数据更适合数据存储与分析。做 Tableau 时,源数据尽量用“长数据”。
1. 什么是长数据,什么是宽数据?
假设我们有一个产品从一月到十二月的销售额,可以有两种表现方式。
宽数据(Wide)
Store | January | February | March | April | May | June | July | August | September | October | November | December |
A | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000 | 1100 | 1200 |
B | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000 | 1100 | 1200 |
- 同一个变量(Sales)按月份展开成多列。
- 1 月到 12 月其实都是 “Sales 这个变量在不同月份的数值”,只是分散在不同列里。
长数据(Long)
Store | Date | Sales |
A | January | 100 |
A | February | 200 |
A | March | 300 |
B | January | 100 |
B | February | 200 |
B | March | 300 |
- 同一个变量(Sales)集中存放在一列,月份放到另一列。
- 信息量相同,但结构更“整洁”。
工作里常见现象:数据库多是“长数据”,而我们看到的成品报表多是“宽数据”。数据库几乎不会把日期当作一列列的标题来存,因为那其实也是“数据”。
2. 当数据逐日累积时会怎样?
如果从年初开始每天都有销售额:
- 宽数据:每天都会“多一列”。一年下来单店能到 365 列,列数飞起,且每列只有寥寥几行,极不友好。
Store | 2024-01-01 | 2024-01-02 | 2024-01-03 | 2024-01-04 | 2024-01-05 | 2024-01-06 | 2024-01-07 | 2024-01-08 | 2024-01-09 | 2024-01-10 | 2024-01-11 | 2024-01-12 |
A | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000 | 1100 | 1200 |
B | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000 | 1100 | 1200 |
需要我把它也转换成长数据(Store、Date、Value 三列)或插入到某个页面吗?
- 长数据:每天只是“多一行”。
Store | Date | Sales |
A | 2024-01-01 | 100 |
B | 2024-01-01 | 100 |
A | 2024-01-02 | 200 |
B | 2024-01-02 | 200 |
A | 2024-01-03 | 300 |
B | 2024-01-03 | 300 |
A | 2024-01-04 | 400 |
B | 2024-01-04 | 400 |
A | 2024-01-05 | 500 |
B | 2024-01-05 | 500 |
这就是为何宽数据当“Tableau 数据源”会别扭。把 2024-01-01、2024-01-02 放在列标题上,本质上是把“数据”硬塞进了“列名”。
要点 1:在导入 Tableau 之前,优先把数据整理为“长数据”,而不是“宽数据”。
3. 两种格式的使用场景
- 宽数据适合“人眼扫读”。例如横向看 12 个月的数值,很直观,年底加一列 Total 就是一张常见年报。
- 长数据适合“存储、筛选、计算与建模”。比如要找 Store=A 且 Date=2024-02-01 的记录,长数据过滤两下就能锁定。
总结:宽数据适合展示,长数据适合保存与提取。
4. 长宽转换与 Tableau 的意义
不同数据库/工具对宽↔长转换都有一套:Excel 的 Pivot/Unpivot,Python 的 pivot/melt,SQL 的 UNPIVOT…
Tableau 的贡献之一,是让这件事“拖拖拽拽就能办”。很多项目的目标,就是把机器友好的“长数据”转换成用户友好的“宽表格”,哪怕只是把复杂长表变成可读宽表,已经能极大提升表达效果。
5. 解读长数据的常见模式:Dimension + Fact
打开 Sample Superstore(只看 Orders 表)。你会发现:
- 左侧“文字型”为主的列通常是蓝色图标,称为 Dimension(维度),用于描述“是谁、是什么、在哪里、什么时候”。这些信息一般“不会随时间变化”,例如性别、产品类别等。
- 右侧“数值型”为主的列通常是绿色图标,称为 Fact(事实/记录),用于记录“发生了什么、数量多少、金额多少”,通常“会随时间变化”。
我也常用一个顺口的区分法:
- 不太随时间变的,偏描述性的,八成是 Dimension。
- 经常随时间变、需要汇总/计算的,通常是 Fact。
6. 长数据还有“进阶款”:单列 Fact 的结构(超纲,先点到)
有些图怎么都做不出来,不一定是你 Tableau 技术不行,可能是“数据结构不对口”。有种进阶的长数据结构,会把多个数值列(Sales、Cost…)再“压”成一列 Value,并用另一列 Variable 指明当前这行到底是 Sales 还是 Cost(或 Weight、Delivery 等)。
原始(常规)结构:Dimension + 多个 Fact 列(Sales、Cost…)
Store | Product | Date | Sales | Cost |
A | Bread | 2024-01-01 | 100 | 50 |
A | Milk | 2024-01-01 | 100 | 50 |
A | Bread | 2024-01-02 | 200 | 100 |
A | Milk | 2024-01-02 | 200 | 100 |
A | Bread | 2024-01-03 | 300 | 150 |
A | Milk | 2024-01-03 | 300 | 150 |
A | Bread | 2024-01-04 | 400 | 200 |
A | Milk | 2024-01-04 | 400 | 200 |
A | Bread | 2024-01-05 | 500 | 250 |
A | Milk | 2024-01-05 | 500 | 250 |
进阶结构:Dimension + Variable + Value(把多列 Fact 熔成一列)
Store | Product | Date | Variable | Value |
A | Bread | 2024-01-01 | Sales | 100 |
A | Bread | 2024-01-02 | Sales | 200 |
A | Bread | 2024-01-03 | Sales | 300 |
A | Bread | 2024-01-04 | Sales | 400 |
A | Bread | 2024-01-05 | Sales | 500 |
A | Bread | 2024-01-01 | Cost | 50 |
A | Bread | 2024-01-02 | Cost | 100 |
A | Bread | 2024-01-03 | Cost | 150 |
A | Bread | 2024-01-04 | Cost | 200 |
A | Bread | 2024-01-05 | Cost | 250 |
好处:
- 新增一种指标,不必再加一列,只要在 Variable 里多一个取值即可。
- 某些可视化或对比(如指标切换、同轴对比、条件着色)会更“顺手”。
先埋个种子:不同图表对“数据形态”的要求不同。做不出图时,先检查你的数据结构是否匹配该图表的“口味”。后续我会专门开一节讲解“哪些图需要单列 Fact 的长数据”。