使用 Tcl 计算列的列的平均值

Calculate average of columns of column with Tcl

我想用 tcl 计算此列的平均值 请帮助我

frame     Elec
1          50  
2          40
3          30
4          20

如果这是一个独立的脚本,(警告:提前自我提升),我写了一个 program called tawk 就像 awk 除了使用 TCL 编写脚本,它为你做了大部分工作:

$ tawk 'line {$NR > 1} { incr sum $F(2) }
        END { puts [expr {double($sum) / ($NR - 1)}] }' input.txt
35
# Equivalent awk:
$ awk 'NR > 1 { sum +=  } END { print (sum / (NR - 1)) }' input.txt
35

如果它是较大程序的一部分,您必须自己打开文件并读取和拆分行。也许像

# Column number is 1-based
proc avg_column {filename column} {
    set f [open $filename r]
    gets $f ;# Read and discard header line
    set sum 0
    set nlines 0
    while {[gets $f line] >= 0} {
        set columns [regexp -all -inline {\S+} $line]
        incr sum [lindex $columns $column-1]
        incr nlines
    }
    close $f
    return [expr {double($sum) / $nlines}]
}

puts [avg_column input.txt 2]

不是答案,而是一些提示。您需要:

  • open 文件
  • gets阅读header
  • 使用 while 循环读取文件的行
  • 使用split or regexp获取第二个字段
  • 如果值只是整数
  • ,则用 expr, or incr 求和(并计算行数)

如果您的输入恰好是(某种 CSV),或者您可以将其引导到这个方向,那么您可以使用 tcllib 的 csv 包:

package require csv
package require struct::matrix

struct::matrix dm
set f [open mydata.csv]
while {[gets $f l] >= 0} {
    # sanitize input, line-wise
    set l [regsub -all {\s+} $l " "]
    csv::split2matrix dm $l " " auto
}
close $f

set columnData [lrange [dm get column 1] 1 end]; # strip off header
puts [expr {double([tcl::mathop::+ {*}$columnData])/[llength $columnData]}]; # compute avg

一些提示:

  • gets 将逐行读取您的输入文件;
  • csv::split2matrix 将每一行放入 struct::matrix;
  • /matrix/ get column /n/ 允许访问一个数据列(包括 header 字段);
  • tcl::mathop::+ 可以访问 built-in 加法运算符(在 [expr] 命令之外)并支持 2+ 加数。