2

我有一个sample.dat文件,其中包含随时间记录的 10 个不同字段的实验值。使用或任何其他 shell 工具sedawk我需要编写一个读取 sample.data 文件的脚本,并为每个字段计算最大值、最小值和平均值。

sample.dat

字段1:实验1:10.0
字段2:实验1:12.5
字段1:实验2:5.0
字段 2:实验 2:14.0
字段1:实验3:18.0
字段2:实验3:3.5

输出

字段 1:MAX = 18.0,MIN = 5.0,AVERAGE = 11.0
字段 2:MAX = 14.0,MIN = 3.5,AVERAGE = 10.0
4

5 回答 5

3
awk -F: '
{
    sum[$1]+=$3;
    if(!($1 in min) || (min[$1]>$3))
        min[$1]=$3;
    if(!($1 in max) || (max[$1]<$3))
        max[$1]=$3;
    count[$1]++
}
END {
  for(element in sum)
      printf("%s: MAX=%.1f, MIN=%.1f, AVARAGE=%.1f\n",
              element,max[element],min[element],sum[element]/count[element])
}' sample.dat

输出

field1: MAX=18.0, MIN=5.0, AVARAGE=11.0
field2: MAX=14.0, MIN=3.5, AVARAGE=10.0
于 2013-05-15T18:46:28.103 回答
2

这是我制作的 Perl 解决方案(将文件名替换为您使用的任何文件):

#!/usr/bin/perl

use strict;
use warnings;
use List::Util qw(max min sum);

open( my $fh, "<", "sample.dat" ) or die $!;

my %fields;
while (<$fh>) {
    chomp;
    $_ =~ s/\s+//g;
    my @line = split ":";
    push @{ $fields{ $line[0] } }, $line[2];
}

close($fh);

foreach ( keys %fields ) {
    print "$_: MAX="
      . max @{ $fields{$_} };
    print ", MIN="
      . min @{ $fields{$_} };
    print ", AVERAGE="
      . ( (sum @{ $fields{$_} }) / @{ $fields{$_} } ) . "\n";
}
于 2013-05-15T19:09:19.967 回答
2

bashbc:_

#!/bin/bash

declare -A min
declare -A max
declare -A avg
declare -A avgCnt

while read line; do
  key="${line%%:*}"
  value="${line##*: }"
  if [ -z "${max[$key]}" ]; then
    max[$key]="$value"
    min[$key]="$value"
    avg[$key]="$value"
    avgCnt[$key]=1
  else
    larger=`echo "$value > ${max[$key]}" | bc`
    smaller=`echo "$value < ${min[$key]}" | bc`
    avg[$key]=`echo "$value + ${avg[$key]}" | bc`
    ((avgCnt[$key]++))
    if [ "$larger" -eq "1" ]; then
      max[$key]="$value"
    fi
    if [ "$smaller" -eq "1" ]; then
      min[$key]="$value"
    fi
  fi
done < "$1"

for i in "${!max[@]}"
do
  average=`echo "${avg[$i]} / ${avgCnt[$i]}" | bc`
  echo "$i: MAX = ${max[$i]}, MIN = ${min[$i]}, AVERAGE = $average"
done
于 2013-05-16T09:47:03.397 回答
1

您可以使用此 python 代码:

from collections import defaultdict
d = defaultdict(list)
[d[(line.split(":")[0])].append(float(line.split(":")[2].strip("\n "))) for line in open("sample.dat")]
for f in d:  print f, ": MAX=", max(d[f]),", MIN=", min(d[f]),", AVG=", sum(d[f])/float(len(d[f]))
于 2013-05-16T06:00:12.173 回答
0

你可以使用gnu-R这样的东西:

echo "1" > foo
echo "2" >> foo

cat foo \
| r -e \
' 
  f <- file("stdin")
  open(f)
  
  v <- read.csv(f,header=F)
  write(max(v),stdout())
'

2

对于汇总统计,

cat foo \
| r -e \
' 
  f <- file("stdin")
  open(f)
  
  v <- read.csv(f,header=F)
  write(summary(v),stdout())
'

# Max, Min, Mean, median, quartiles, deviation, etc.
...

在json中:

... | r -e \
'
  library(rjson)
  f <- file("stdin")
  open(f)
  v <- read.csv(f,header=F)
  json_summary <- toJSON(summary(v))
  write(json_summary,stdout())
'

# same stats 

| jq '.Max'

# for maximum

如果您使用的是 linux 命令行环境,那么您可能不想重新实现轮子,保持矢量化,并拥有易于阅读和开发的干净代码,并且执行一些标准的、可组合的功能

在这种情况下,您不需要面向对象的语言(使用 python 会导致界面和代码膨胀以及使用 google、pip 和 conda 进行迭代,具体取决于您需要的库和必须手动编码的类型转换),您不需要冗长的语法,默认情况下您可能需要处理数据帧/向量/行/列的数值数据。

您可能还需要可以在您的特定机器上毫无问题地浮动的脚本。如果你在 Linux 上,那可能意味着:gnu-R。通过apt-get.

于 2019-09-16T15:21:33.777 回答