如何用批处理批量编辑CSV表头标签并实现行转列?
解决CSV多行转宽格式的批处理脚本问题
问题背景
现有单个表头多行数据的CSV文件,每个研究对象对应独立文件夹,表头中的数字为对象ID,原结构如下:
region,travelnum,seatnum,1.Stat.Money.Min,1.Stat.Money.Avg,1.Stat.Money.Med,1.Stat.Money.Max,1.Stat.Money.Std,1.Stat.Family.Min,1.Stat.Family.Avg,1.Stat.Family.Med,1.Stat.Family.Max,1.Stat.Family.Std,1.Stat.Travel.Min,1.Stat.Travel.Avg,1.Stat.Travel.Med,1.Stat.Travel.Max,1.Stat.Travel.Std,1.Stat.Job.Min,1.Stat.Job.Avg,1.Stat.Job.Med,1.Stat.Job.Max,1.Stat.Job.Std A and B,324,8714,0.48,(...), C and D,199,1733,0.32,(...), E and F,915,2501,0.72,(...), ...
需要将其转换为一行表头+一行多列值的宽格式,方便构建DataFrame,目标格式如下:
name,A_and_B_travelnum,A_and_B_seatnum,A_and_B_Money_Min,A_and_B_Money_Avg,A_and_B_Money_Med,A_and_B_Money_Max,A_and_B_Money_Std,A_and_B_Family_Min,A_and_B_Family_Avg,A_and_B_Family_Med,A_and_B_Family_Max,A_and_B_Family_Std,A_and_B_Travel_Min,A_and_B_Travel_Avg,A_and_B_Travel_Med,A_and_B_Travel_Max,A_and_B_Travel_Std,A_and_B_Job_Min,A_and_B_Job_Avg,A_and_B_Job_Med,A_and_B_Job_Max,A_and_B_Job_Std,C_and_D_travelnum,C_and_D_seatnum,C_and_D_Money_Min,C_and_D_Money_Avg,C_and_D_Money_Med,C_and_D_Money_Max,C_and_D_Money_Std,C_and_D_Family_Min,C_and_D_Family_Avg,C_and_D_Family_Med,C_and_D_Family_Max,C_and_D_Family_Std,C_and_D_Travel_Min,C_and_D_Travel_Avg,C_and_D_Travel_Med,C_and_D_Travel_Max,C_and_D_Travel_Std,C_and_D_Job_Min,C_and_D_Job_Avg,C_and_D_Job_Med,C_and_D_Job_Max,C_and_D_Job_Std,... 1,324,8714,0.48,(...),199,1733,0.32,(...),...
原批处理脚本无法正确拼接数据行的所有字段值,以下是修正后的完整脚本:
修正后的批处理脚本
@echo off setlocal EnableDelayedExpansion EnableExtensions :: 定义地区名称映射(空格转下划线) set "region[A and B]=A_and_B" set "region[C and D]=C_and_D" set "region[E and F]=E_and_F" :: 定义统计指标名称映射(去掉前缀.Stat) set "metric[.Stat.Money.Min]=Money_Min" set "metric[.Stat.Money.Avg]=Money_Avg" set "metric[.Stat.Money.Med]=Money_Med" set "metric[.Stat.Money.Max]=Money_Max" set "metric[.Stat.Money.Std]=Money_Std" set "metric[.Stat.Family.Min]=Family_Min" set "metric[.Stat.Family.Avg]=Family_Avg" set "metric[.Stat.Family.Med]=Family_Med" set "metric[.Stat.Family.Max]=Family_Max" set "metric[.Stat.Family.Std]=Family_Std" set "metric[.Stat.Travel.Min]=Travel_Min" set "metric[.Stat.Travel.Avg]=Travel_Avg" set "metric[.Stat.Travel.Med]=Travel_Med" set "metric[.Stat.Travel.Max]=Travel_Max" set "metric[.Stat.Travel.Std]=Travel_Std" set "metric[.Stat.Job.Min]=Job_Min" set "metric[.Stat.Job.Avg]=Job_Avg" set "metric[.Stat.Job.Med]=Job_Med" set "metric[.Stat.Job.Max]=Job_Max" set "metric[.Stat.Job.Std]=Job_Std" :: 遍历所有研究对象文件夹 for /d %%y in (*) do ( set "id=%%y" call :process_csv ) goto :EOF :process_csv :: 输出文件(避免覆盖原文件) set "output_file=!id!\name_updated.csv" :: 初始化表头和数据行变量 set "new_header=name" set "new_data=!id!" :: 读取原CSV的表头行(第一行) for /f "usebackq delims=" %%h in ("!id!\name.csv") do ( set "header_line=%%h" goto :read_header_done ) :read_header_done :: 读取原CSV的数据行(跳过第一行) for /f "usebackq skip=1 delims=" %%r in ("!id!\name.csv") do ( set "row_data=%%r" :: 拆分地区和对应指标值 for /f "tokens=1* delims=," %%a in ("!row_data!") do ( set "current_region=%%a" set "values=%%b" :: 获取地区的映射名称 set "region_alias=!region[!current_region!]!" :: 添加travelnum和seatnum的表头与数据 for /f "tokens=1,2* delims=," %%x in ("!values!") do ( set "new_header=!new_header!,!region_alias!_travelnum,!region_alias!_seatnum" set "new_data=!new_data!,%%x,%%y" :: 处理剩余的统计指标值 set "remaining_values=%%z" set "index=3" :: 对应表头中第4个字段(从1开始计数) :: 拆分表头中的统计指标字段 for %%m in (!header_line!) do ( if !index! gtr 3 ( set "metric_key=%%m" :: 去掉表头中的对象ID前缀(如1.Stat... -> .Stat...) set "metric_key=!metric_key:*.=!" set "metric_alias=!metric[!metric_key!]!" set "new_header=!new_header!,!region_alias!_!metric_alias!" :: 拆分剩余值中的对应指标值 for /f "tokens=1* delims=," %%v in ("!remaining_values!") do ( set "new_data=!new_data!,%%v" set "remaining_values=%%w" ) ) set /a index+=1 ) ) ) ) :: 写入新的CSV文件 > "!output_file!" ( echo !new_header! echo !new_data! ) echo 处理完成:!output_file! goto :EOF
关键逻辑说明
- 映射定义:提前定义地区名称和统计指标的别名,确保新表头符合目标格式(如
A and B转A_and_B,.Stat.Money.Min转Money_Min)。 - 表头与数据拼接:
- 初始化新表头为
name,新数据行为对象ID。 - 逐行读取原CSV的数据,拆分地区和对应指标值,将每个字段的别名和值依次拼接到新表头和数据行中。
- 处理统计指标时,去掉表头中的对象ID前缀(如
1.Stat.Money.Min转为.Stat.Money.Min),匹配预定义的指标别名。
- 初始化新表头为
- 文件写入:将拼接好的新表头和数据行写入新的CSV文件,避免覆盖原文件。
内容的提问来源于stack exchange,提问作者Étalo César Porto Xavier
相关产品推荐
相关产品推荐

