问题:

问题:

我想计算 .txt 文件中特定列的中值,输出该值,并说明该输出值是否正常。我可以执行初始步骤并输出中值,但是不能说明输出值是否在可接受的范围内。

我收到包含以下代码的语法错误消息:

sort -nk9 filename | awk '{a[i++]=$9;} END {x=int((i+1)/2); y=((a[x-1] + a[x])/2); z=(a[x-1]);
if ((y >= 0.5 && y <= 2) || (z >= 0.5 && z <=2));
   {if (x < (i+1)/2) 
   print "Median OR =", y "ALL OK"; 
   else print "Median OR =", z "ALL OK"}; 
else print "ERROR - OR outside range 0.5 - 2.0"}'

答案1

我想这就是你想要的

awk '{sum+=$9;a[x++]=$9;b[$9]++}b[$9]>Mode{Mode=$9}END{print "Mean: " sum/x "\nMedian: "a[int((x-1)/2)]"\nMode: " Mode}' file

布置得比较整齐

awk '
{
     sum+=$9
     a[x++]=$9
     b[$9]++
}
b[$9]>Mode{Mode=$9}
END{
    print "Mean: " sum/x 
    print "Median: "a[int((x-1)/2)] 
    print "Mode: " Mode
}' file

另外,我将为比较添加一些逻辑,但我实际上不知道您要比较什么,因为您的变量只是称为 x,y,z 并且可能有也可能没有正确的方程

答案2

我很感激所提供的代码user78605,因为它指导我如何在查询中找到中位数。然而,上述代码忽略了正确计算中位数所需的某些条件。

问题:

  1. 不应计算空白尾行(如果它们存在于文件中),因为对它们进行计数会影响数据大小,从而影响平均值、中位数、众数以及其他统计量。对于没有数值的行(id est:"abc""28b""h2f"""等),很可能应该执行相同的操作。
  2. 中位数不是原始数据集的中间值,而是有序数据集。也就是说,要找到中位数的数据必须首先排序。
  3. 如果有序数据集中值的数量是偶数,则必须取中间两个值的平均值。
  4. 众数是频率最高的值。数据集可能具有不止一种众数,在这种情况下,需要将两个或多个值列为众数。

以下是我对代码的扩展,考虑到上述条件:

awk -F',' '
{col=$1}{if((col ~  /^-?[0-9]*([.][0-9]+)?$/) && ($0!=""))                 
{
     sum+=col;
     a[x++]=col;
     b[col]++
     if(b[col]>hf){hf=b[col]}
}
}
END{n = asort(a);idx=int((x+1)/2)
     print "Mean: " sum/x
     print "Median: " ((idx==(x+1)/2) ? a[idx] : (a[idx]+a[idx+1])/2)
     for (i in b){if(b[i]==hf){(k=="") ? (k=i):(k=k FS i)}{FS=","}}
     print "Mode: " k
}' file

解释:

问题 #1 的解决方案:

col=$1#如果存储在变量中,则更容易更改列。
(col ~ /^-?[0-9]*([.][0-9]+)?$/)#字符串只能包含数字、句点(小数分隔符)或破折号(减号)。 [仅忽略科学记数法。]
($0!="")#整行不能为空。

对符合条件的行执行以下循环操作:

sum+=col#(缩写sum=sum+col。)所有值的总和。
a[x++]=col#每个值都存储到一个数组中。
b[col]++# 中的值col被视为 array 的代理键b。因此 中 的元素b数量与 中唯一值的数量一样多col。该迭代器创建频率计数数组。 (缩写b[col]=b[col]+1。)
if(b[col]>hf){hf=b[col]}#让hf代表“最高频率”。循环遍历所有频率并hf仅在找到更高频率时更新。hf最初是“”(什么也没有)。

问题 #2 的解决方案:
循环操作完成后:

对数组中存储的值进行排序:n = asort(a)

值得注意的是,数组的原始索引范围a是从“0”到“x-1”。除了排序之外,新的索引范围是从“1”到“x”。这就是为什么我使用int((x+1)/2)而不是
int((x-1)/2)作为保存中位数的索引 - 或两个数字中较小的一个,将平均为中位数。

问题 #3 的解决方案:

((idx == (x+1)/2) ? a[idx] : (a[idx]+a[idx+1])/2)
这是 if-else 结构的简写符号:
如果int((x+1)/2)等于,(x+1)/2则值的数量为奇数,中位数为a[idx]。如果不是这样,int()将向下舍入(x+1)/2到最接近的整数,表示值的数量是偶数。在这种情况下,a[idx]和的平均值a[idx]+1将是中位数。

问题 #4 的解决方案:

for (i in b) {if(b[i]==hf){(k=="") ? (k=i):(k=k FS i)}{FS=","}}
由于hf是代表数据集中最高频率的值,因此如果 b 的任何值等于hf,则其代理键是众数,或至少其中一个众数。
此代码连接所有与i条件匹配的代理键 ,并将它们存储到变量 中,k该变量可以打印在标题为“Mode”的一行上。

进一步调整:

-F应根据文件中用作列分隔符的字符进行调整。

如果文件的第一行有标题,请NR > 1{col=$1}.

FS用于将两个变量连接在一起。FS当选择不使用分隔符时,使用尤为有用。那是,FS=""

数据

以下数据用于实验以创建脚本:

10
20
10
20.5
50
30
40
50
10
30
20.5


-h
h

4.35
-537
0
-0

30
d




.

结果:

Mean: -13.2281
Median: 20.25
Mode: 10,30

相关内容