You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用批处理批量编辑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)。
  • 表头与数据拼接:
    1. 初始化新表头为name,新数据行为对象ID。
    2. 逐行读取原CSV的数据,拆分地区和对应指标值,将每个字段的别名和值依次拼接到新表头和数据行中。
    3. 处理统计指标时,去掉表头中的对象ID前缀(如1.Stat.Money.Min转为.Stat.Money.Min),匹配预定义的指标别名。
  • 文件写入:将拼接好的新表头和数据行写入新的CSV文件,避免覆盖原文件。

内容的提问来源于stack exchange,提问作者Étalo César Porto Xavier

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 22:08:08