计算多行中位数

时间:2015-10-07 08:24:33

标签: bash

我有一个文件名数字,只包含一堆随机数

1     2     3
7     5     9
2     2     9
5     4     5
7     2     6

我必须创建一个脚本来查找每行的中位数,这是我的代码:

while read -a row
do
  for i in "${row[@]}"
  do

    length=`expr ${#row[@]} % 2`
    if [ $length -ne 0 ] ; then
      mid=`expr ${#row[@]} / 2`
      echo ${row[middle]}
    elif [ $length -eq 0 ] ; then
      val1=`expr ${#row[@]} / 2`
      val2=`expr (${$row[@]} / 2) + 1`
      mid=`expr ($val1 + $val2) / 2`
      echo $mid
  done | sort -n
done < numbers

但是这不起作用,而是显示错误。我在这段代码中犯了什么错误?另外我还没弄清楚放置sort -n的正确方法在哪里,因为在计算中位数之前需要先对它进行排序,对吗?

2 个答案:

答案 0 :(得分:1)

Bash只能进行整数运算,你需要像bc这样的工具来计算平均值:

#!/bin/bash
while read -a n ; do
    n=($(IFS=$'\n' ; echo "${n[*]}" | sort -n))
    len=${#n[@]}
    if (( len % 2 )) ; then
        echo ${n[ len / 2 ]}
    else
        bc -l <<< "scale=1; (${n[ len / 2 - 1 ]} + ${n[ len / 2 ]}) / 2"
    fi
done

我可能会找到更高级别的语言,例如的Perl:

#!/usr/bin/perl
use warnings;
use strict;

while (<>) {
    my @n = sort { $a <=> $b } split;
    print @n % 2 ? $n[ @n / 2 ]
                 : ($n[ @n / 2 - 1 ] + $n[ @n / 2 ]) / 2,
          "\n";
}

答案 1 :(得分:0)

我只是为了它的乐趣而不得不放弃它。

请注意,我不使用if,而是使用一小部分索引。

awk '{
  split($0,a)    # create array a from input line
  asort(a,b)     # sort array into array b (gnu awk specific)
  # add twice the median, or around the median and divide by 2
  print ( b[int(NF/2+0.7)] + b[int(NF/2+1.2)] )/2
}' numbers

缩短(67个字符):

awk '{split($0,a);asort(a,b);print(b[int(NF/2+0.7)]+b[int(NF/2+1.2)])/2}' numbers
66 prs golf: - )

awk '{split($0,a);asort(a,b);$0=(b[int(NF/2+0.7)]+b[int(NF/2+1.2)])/2}1' numbers