Bash线性回归程序执行停滞,无法输出均值与标准差求助
问题分析与修复方案
一、当前程序停滞的核心原因及修复点
1. CSV读取分隔符错误
你用IFS='.'读取CSV文件,但绝大多数CSV是逗号分隔,这会导致每行数据无法被正确拆分,后续x、y数组内容完全错误,直接导致计算逻辑卡死。
修复:将IFS='.'改为IFS=',',并在拆分每行数据时显式指定分隔符。
2. 数据拆分逻辑失效
原代码中row=("${array[$i]}")只是把整行字符串赋值给数组的单个元素,没有拆分出x和y值。需要用read -ra结合IFS来拆分每行。
3. 标准差计算函数的致命错误
- 参数传递混乱:调用时传入
"${x[@]}" "$x_mean",但函数里local data=("${@}")会把均值也混入数据数组,导致mean=$1取的是第一个数据而非传入的均值。 - 未定义
diff变量:循环中直接使用diff*diff,awk无法识别该变量,导致计算停滞。
4. 均值计算的低效问题
原代码用Bash循环逐次调用awk累加,不仅速度慢,还容易出现数值精度问题,建议直接用awk一次性完成计算。
二、修复后的完整代码
#!/bin/bash # Variables for data src="data.csv" # Read data and skip header readarray -t array < <(awk 'NR>1' "$src") # Display content for item in "${array[@]}"; do echo "$item" done # Initialize variables x and y x=() y=() # Data separation loop (comma-separated CSV) for row_str in "${array[@]}"; do IFS=',' read -ra row <<< "$row_str" x+=("${row[0]}") y+=("${row[1]}") done # Calculate mean with awk (efficient batch processing) calculate_mean() { printf "%s\n" "${@}" | awk '{sum += $1} END {print sum/NR}' } # Calculate standard deviation calculate_std_deviation() { local mean="$1" shift # Remove mean from parameter list, remaining are data points printf "%s\n" "${@}" | awk -v mean="$mean" '{sum_sq += ($1 - mean)^2} END {print sqrt(sum_sq/NR)}' } x_mean=$(calculate_mean "${x[@]}") x_std=$(calculate_std_deviation "$x_mean" "${x[@]}") y_mean=$(calculate_mean "${y[@]}") y_std=$(calculate_std_deviation "$y_mean" "${y[@]}") echo "Mean x: $x_mean" echo "Standard deviation x: $x_std" echo "Mean y: $y_mean" echo "Standard deviation y: $y_std"
三、Bash中实现线性回归的高效思路
Bash本身不擅长数值运算,建议尽量用awk处理核心计算,避免Bash数组的繁琐操作:
- 直接用awk完成全流程计算:跳过Bash拆分x、y数组的步骤,让awk直接读取CSV,计算均值、协方差、方差,进而得出线性回归的斜率和截距。
- 示例awk核心计算代码:
BEGIN {FS=","} # 指定CSV分隔符 NR==1 {next} # 跳过表头 { x_sum += $1; y_sum += $2 x_sq_sum += $1*$1; xy_sum += $1*$2 n++ } END { x_mean = x_sum / n y_mean = y_sum / n cov_xy = (xy_sum / n) - x_mean*y_mean var_x = (x_sq_sum / n) - x_mean*x_mean slope = cov_xy / var_x intercept = y_mean - slope*x_mean print "Slope: " slope print "Intercept: " intercept }
你可以将这段代码保存为regression.awk,然后在Bash脚本中调用:awk -f regression.awk data.csv。
内容的提问来源于stack exchange,提问作者Luthfi Hakim
相关产品推荐
相关产品推荐

