4、数据格式与结构:理解常见数据格式(CSV、Excel、JSON)及数据结构(长表、宽表),并学会转换

在健康数据趋势分析中,数据以多种格式存储和交换。CSV、Excel 和 JSON 是最常见的三种载体,而长表与宽表则决定了数据在分析工具中的组织方式。许多分析项目在起步阶段就因格式解析错误或表结构选择不当而返工。本章将系统讲解三种格式的底层逻辑、适用场景,以及长宽表转换的核心方法,帮助你在拿到原始数据后,能快速判断其结构并完成标准化处理。

数据格式与结构转换路径图 CSV 纯文本/逗号分隔 适合批量导入 Excel 多工作表/格式丰富 适合人工维护 JSON 嵌套/键值对 适合API传输 解析与标准化 处理缺失值 / 统一日期格式 / 去除重复记录 / 类型转换 宽表(Wide Format) 每行=一个主体,每列=一个指标 适合回归/相关性分析 例:ID, 血压_1月, 血压_2月 长表(Long Format) 每行=一个观测点 适合时间序列/分组聚合 例:ID, 月份, 血压值 pivot / melt

4.1 核心原理:三种格式的本质与选择逻辑

CSV(逗号分隔值) 是一种纯文本格式,每行代表一条记录,字段间用逗号(或其他分隔符)隔开。它的核心优势在于通用性极强——几乎所有数据分析工具(Python、R、SQL、Tableau)都能直接读取,且文件体积小、编码透明。但缺点是不支持数据类型定义,所有内容默认以字符串存储,日期和数值需要二次转换。

Excel(.xlsx) 是二进制格式,支持多工作表、单元格样式、公式、数据验证和图表。在健康数据场景中,Excel 常用于人工录入和初步整理,例如医院科室上报的月度体检汇总表。但 Excel 在自动化流水线中并不友好:读取速度慢、依赖特定库(如 openpyxl)、且容易因单元格合并或公式引用导致解析错误。

JSON(JavaScript Object Notation) 是一种轻量级数据交换格式,以键值对和嵌套数组表达复杂关系。健康设备(如智能手环、血压计)的 API 接口通常返回 JSON 数据,因为它能自然表达层级结构,例如一个患者包含多个测量记录。JSON 的缺点是冗余字符多(大括号、引号),不适合超大文件存储,且嵌套过深时难以直接用于表格分析。

选择格式的核心原则是:数据从哪来、到哪去、中间谁在处理。如果数据要进入数据库或统计软件,CSV 是首选;如果数据需要人工审核和标注,Excel 更合适;如果数据来自 Web API 或需要保留嵌套关系,JSON 不可替代。

4.2 判断方法:如何快速识别数据格式与结构

拿到一个数据文件后,不要急于导入分析工具,先通过以下三个步骤判断其格式和结构:

  1. 查看文件扩展名和首行内容:CSV 文件用文本编辑器打开后,首行通常是字段名,后续行以逗号分隔;Excel 文件无法用文本编辑器直接查看,需要打开软件检查工作表数量;JSON 文件首字符一定是 { 或 [,且包含明显的键名和冒号。
  2. 检查数据维度:用 Excel 或 Python 的 shape 属性查看行列数。如果列数很多(如几十列)且每列代表不同指标,大概率是宽表;如果行数远大于列数,且有一列是“时间”或“分组”字段,可能是长表。
  3. 观察重复模式:在长表中,同一主体的 ID 会重复出现多次,且每次对应不同的时间点或条件;在宽表中,每个主体只出现一次,但列名会包含时间后缀(如 血压_2024_01)。

以下是一个快速判断表,帮助你根据数据特征选择正确的处理方式:

特征宽表长表
行含义一个主体(患者/设备/地区)一个观测点(主体×时间×指标)
列含义不同指标或不同时间点的值变量名(如“血压”)+ 变量值
典型场景横截面比较、相关性分析时间序列、分组统计、ggplot绘图
存储效率列多但行少,可能有大量空值行多但列少,冗余较少
转换方向宽→长:使用 melt 或 pivot_longer长→宽:使用 pivot 或 pivot_wider

4.3 操作流程:格式解析与长宽表转换实战

以 Python 的 Pandas 库为例,我们演示从 JSON 到 CSV、从宽表到长表的完整流程。假设你从健康管理平台导出了一个 JSON 文件,包含三位患者三个月的血压记录:

// 原始 JSON 数据(部分)
[
  {"patient_id": "P001", "month": "2024-01", "systolic": 128, "diastolic": 82},
  {"patient_id": "P001", "month": "2024-02", "systolic": 135, "diastolic": 88},
  {"patient_id": "P002", "month": "2024-01", "systolic": 142, "diastolic": 95}
]

第一步,使用 pd.read_json() 读取数据,此时得到的是长表结构(每行一个患者-月份组合)。第二步,如果我们需要比较不同患者在同一月份的血压差异,可以将其转换为宽表:

import pandas as pd

df = pd.read_json('blood_pressure.json')
# 宽表转换:行=患者,列=月份,值=收缩压
wide_df = df.pivot(index='patient_id', columns='month', values='systolic')
wide_df = wide_df.reset_index()
print(wide_df)

输出结果如下:

patient_id  2024-01  2024-02
P001        128      135
P002        142      NaN

第三步,如果后续需要做时间趋势图,我们又要将宽表还原为长表:

long_df = wide_df.melt(id_vars='patient_id', var_name='month', value_name='systolic')
long_df = long_df.dropna(subset=['systolic'])
print(long_df)

在 Excel 中,你可以使用“数据透视表”和“Power Query”实现类似功能。Power Query 的“逆透视列”功能对应宽表转长表,“透视列”对应长表转宽表,操作路径为:数据 → 从表格/范围 → 转换 → 逆透视列。

4.4 案例拆解:某社区健康体检数据的格式统一

背景与约束:某社区卫生服务中心需要汇总 2024 年四个季度的居民体检数据。原始数据来自三个渠道:① 体检系统导出的 CSV 文件(宽表,每行一个居民,列包含 Q1-Q4 的血糖值);② 护士手工录入的 Excel 表(长表,每行一条记录,包含居民 ID、季度、血糖值);③ 上级平台推送的 JSON 文件(嵌套结构,包含居民基本信息及每次测量的详细字段)。

初始现象与目标:三个文件无法直接合并,因为结构不一致。目标是将所有数据统一为“长表”格式,并导出为 CSV 供统计分析使用。

关键输入数据:CSV 文件有 2000 行、9 列(ID、姓名、Q1_血糖、Q2_血糖、Q3_血糖、Q4_血糖、Q1_血压、Q2_血压);Excel 文件有 3500 行、4 列(ID、季度、血糖值、血压值);JSON 文件包含 500 条记录,每条记录有 id、name、measurements 数组,数组内每个元素含 quarter、glucose、bp_systolic。

分析判断过程:首先,将 CSV 宽表用 melt 转换为长表,提取季度和血糖值;其次,Excel 表结构已符合长表要求,只需统一列名;最后,JSON 需要先展平嵌套的 measurements 数组,再提取字段。合并前还需处理 ID 格式不一致问题(CSV 中为“001”,JSON 中为“P001”)。

实际操作步骤:

  1. 用 Python 读取 CSV,执行 pd.melt(df, id_vars=['ID','姓名'], value_vars=['Q1_血糖','Q2_血糖','Q3_血糖','Q4_血糖'], var_name='季度', value_name='血糖值'),并映射季度名称。
  2. 读取 Excel 文件,重命名列为 ID、季度、血糖值、血压值。
  3. 解析 JSON:使用 json.load() 后循环提取,或使用 pd.json_normalize() 将嵌套数组拆分为多行。
  4. 统一 ID 格式:去除前导字母,保留数字部分。
  5. 使用 pd.concat() 纵向合并三个数据框,并删除重复记录(同一 ID 同一季度只保留一条)。

结果对比:合并前,三个文件无法直接比较;合并后得到 6000 行标准长表,可直接用于季度趋势分析和居民血糖异常筛查。处理耗时约 15 分钟,而手动复制粘贴预计需要 3 小时。

风险与代价:合并过程中发现 12 条记录存在血糖值明显异常(如 35 mmol/L),经核实为录入错误,已剔除。若未做数据验证,这些异常值会严重影响后续统计。

复盘经验:多源数据合并前,务必先绘制“数据结构映射表”,明确每个字段的来源和目标列名;同时建立数据质量检查规则(如范围校验、非空校验),避免脏数据进入分析流程。

4.5 常见误区与总结复盘

误区一:认为 CSV 就是“简单版 Excel”。实际上,CSV 不保存公式、样式和数据类型,如果直接用 Excel 打开并另存为 CSV,可能会导致日期格式变化或长数字被科学计数法显示。建议在导出 CSV 时,将日期列改为 YYYY-MM-DD 格式,数值列保留两位小数。

误区二:长表和宽表哪个“更好”。没有优劣,取决于分析目的。做回归分析时宽表更方便(每列是一个自变量);做时间序列图或分组比较时长表更合适。最佳实践是:存储用长表,分析用宽表,通过脚本快速转换。

误区三:忽略编码问题。CSV 文件常见编码有 UTF-8、GBK、ANSI。如果使用 Python 读取时出现乱码,应指定 encoding='utf-8' 或 encoding='gbk'。JSON 文件统一使用 UTF-8,但要注意某些平台会返回带 BOM 的 UTF-8,需用 utf-8-sig 处理。

误区四:手动转换长宽表。在 Excel 中复制粘贴转置虽然可行,但一旦数据量超过几千行,效率极低且容易出错。建议使用 Power Query 或 Python 脚本,实现可重复的自动化流程。

核心要点回顾:

  • CSV 适合程序间交换,Excel 适合人工维护,JSON 适合 API 数据。
  • 宽表行少列多,长表行多列少;转换工具包括 Pandas 的 pivot/melt 和 Excel 的透视表/逆透视列。
  • 处理多源数据时,先统一 ID 格式和日期格式,再合并。
  • 任何转换操作后都要做数据验证,检查行数、空值率和重复率。

经验提醒:在团队协作中,建议制定一份“数据字典”,明确每个字段的命名规范、数据类型和允许的取值范围。这能大幅减少因格式理解不一致导致的沟通成本。

风险提示:当 JSON 嵌套层级超过三层时,直接展平会导致大量重复数据。此时应考虑拆分为多个关联表(如患者主表和测量明细表),而不是强行合并为一张宽表。