2015-07-21 41 views
0

我有五個不同的文件。每個文件的部分看起來:使用Shell不考慮缺失值的多個文件的平均數

ifile1.txt ifile2.txt ifile3.txt ifile4.txt ifile5.txt 
    2   3   2   3   2 
    1   2   /no value  2   3 
/no value  2   4   3  /no value 
    3   1   0   0   1 
/no value /no value /no value /no value /no value 

我需要計算這五個文件的平均不考慮遺漏值。即

ofile.txt 
    2.4 
    2.0 
    3.0 
    1.0 
    99999 

Here 2.4 = (2+3+2+3+2)/5 
    2.0 = (1+2+2+3)/4 
    3.0 = (2+4+3)/3 
    1.0 = (3+1+0+0+1)/5 
    99999 = all are missing 

我試圖用下面的方式,但不覺得它是一個正確的方法。

paste ifile1.txt ifile2.txt ifile3.txt ifile4.txt ifile5.txt > ofile.txt 
tr '\n' ' ' <ofile.txt> ofile1.txt 
awk '!/\//{sum += $1; count++} {print count ? (sum/count) : count;sum=count=0}' ofile1.txt > ofile2.txt 
awk '!/\//{sum += $2; count++} {print count ? (sum/count) : count;sum=count=0}' ofile1.txt > ofile3.txt 
awk '!/\//{sum += $3; count++} {print count ? (sum/count) : count;sum=count=0}' ofile1.txt > ofile4.txt 
awk '!/\//{sum += $4; count++} {print count ? (sum/count) : count;sum=count=0}' ofile1.txt > ofile5.txt 
awk '!/\//{sum += $5; count++} {print count ? (sum/count) : count;sum=count=0}' ofile1.txt > ofile6.txt 
paste ofile2.txt ofile3.txt ofile4.txt ofile5.txt ofile6.txt > ofile7.txt 
tr '\n' ' ' <ofile7.txt> ofile.txt 
+1

你嘗試過什麼,並且你遇到什麼問題?堆棧溢出不是其他人爲您編寫代碼的網站。 –

+1

我很抱歉讓你感覺如此。老實說,我從過去兩天開始一直在嘗試,但無法以適當的方式去做。無論如何,我已經更新了我嘗試過的問題。 – Kay

回答

2

以下script.awk將提供你想要的東西:

BEGIN { 
    gap = -1; 
    maxidx = -1; 
} 
{ 
    if (NR != FNR + gap) { 
     idx = 0; 
     gap = NR - FNR; 
    } 
    if (idx > maxidx) { 
     maxidx = idx; 
     count[idx] = 0; 
     sum[idx] = 0; 
    } 
    if ($0 != "/no value") { 
     count[idx]++; 
     sum[idx] += $0; 
    } 
    idx++; 
} 
END { 
    for (idx = 0; idx <= maxidx; idx++) { 
     if (count[idx] == 0) { 
      sum[idx] = 99999; 
      count[idx] = 1; 
     } 
     print sum[idx]/count[idx]; 
    } 
} 

你與調用它:

awk -f script.awk ifile*.txt 

,並允許輸入文件的任意號碼,每一個任意行數。它的工作原理如下:


BEGIN { 
    gap = -1; 
    maxidx = -1; 
} 

此開始的行進行處理,並將其設置當前間隙,並相應地最大索引之前部分延伸。

的差距是整體的行號NR和文件行號FNR,用於當您切換文件進行檢測,一些處理多個輸入文件時是非常方便的區別。

最大索引用於計算出最大行數,以便在最後輸出正確數量的記錄。


{ 
    if (NR != FNR + gap) { 
     idx = 0; 
     gap = NR - FNR; 
    } 
    if (idx > maxidx) { 
     maxidx = idx; 
     count[idx] = 0; 
     sum[idx] = 0; 
    } 
    if ($0 != "/no value") { 
     count[idx]++; 
     sum[idx] += $0; 
    } 
    idx++; 
} 

上面的代碼是該溶液中,每行執行的肉。第一個if語句用於檢測您是否剛剛移動到一個新文件中,並且它是這樣做的,因此它可以彙總每個文件中的所有相關行。我的意思是每個輸入文件的第一行用於計算輸出文件第一行的平均值。

第二個if語句會調整maxidx如果當前行號超出我們遇到的任何以前的行號。這是爲了文件一可能有七行,但文件二有九行(在你的情況不是這樣,但它是值得處理的)。以前未知的行號也意味着我們初始化它的總和並計數爲零。

最後的if聲明只是更新總和並計算該行是否包含除/no value以外的任何內容。

然後,當然,您需要調整下一次的行號。


END { 
    for (idx = 0; idx <= maxidx; idx++) { 
     if (count[idx] == 0) { 
      sum[idx] = 99999; 
      count[idx] = 1; 
     } 
     print sum[idx]/count[idx]; 
    } 
} 

在輸出該數據的條件,它是通過陣列去和從所述總和計算的平均值和計數一件簡單的事情。請注意,如果計數爲零(所有對應條目均爲/no value),我們調整總數並計數,以獲得99999。然後我們只打印平均值。


所以,運行該代碼在你輸入文件給出,如要求:

$ awk -f script.awk ifile*.txt 
2.4 
2 
3 
1 
99999 
+0

這真是太棒了@paxdiablo。如果我需要計算標準偏差,你能建議我嗎? – Kay

0

使用bashnumaverage(而忽略非數字輸入),加上pastesedtr(均爲清潔,因爲numaverage需要單列輸入,並且如果輸入是100% text)會引發錯誤:

paste ifile* | while read x ; do \ 
        numaverage <(tr '\t' '\n' <<< "$x") 2>&1 | \ 
        sed -n '1{s/Emp.*/99999/;p}' ; \ 
       done 

輸出:

2.4 
2 
3 
1 
99999