使用awk从第一行中指定的列中的值计算平均值

时间:2017-08-17 22:40:38

标签: bash awk

我有一个巨大的文件(数百行,大约4,000列),结构如下

locus   1   1   1   2   2   3   3   3
exon    1   2   3   1   2   1   2   3
data1   17.07   7.11    10.58   10.21   19.34   14.69   3.32    21.07
data2   21.42   11.46   7.88    9.89    27.24   12.40   0.58    19.82

我需要从所有值(分别在每条数据线上)计算具有相同基因座编号的平均值(即第一行中的相同数字),即

  

data1:来自前三个值的意思(轨迹'1'的三列:   17.07,7.11,10.58),接下来的两个值(10.21,19.34)和接下来的三个值(14.69,3.32,21.07)

我希望有这样的输出

data1   mean1   mean2   mean3
data1   mean1   mean2   mean3

我在考虑使用bash和awk ...... 谢谢你的建议。

3 个答案:

答案 0 :(得分:1)

如果是我,我会使用R,而不是awk

library(data.table)
x = fread('data.txt')

#> x
#      V1    V2    V3    V4    V5    V6    V7   V8    V9
#1: locus  1.00  1.00  1.00  2.00  2.00  3.00 3.00  3.00
#2:  exon  1.00  2.00  3.00  1.00  2.00  1.00 2.00  3.00
#3: data1 17.07  7.11 10.58 10.21 19.34 14.69 3.32 21.07
#4: data2 21.42 11.46  7.88  9.89 27.24 12.40 0.58 19.82

# save first column of names for later
cnames = x$V1

# remove first column
x[,V1:=NULL]

# matrix transpose: makes rows into columns
x = t(x)

# convert back from matrix to data.table
x = data.table(x,keep.rownames=F)

# set the column names
colnames(x) = cnames

#> x
#   locus exon data1 data2
#1:     1    1 17.07 21.42
#...

# ditch useless column
x[,exon:=NULL]

#> x
#   locus data1 data2
#1:     1 17.07 21.42

# apply mean() function to each column, grouped by locus
x[,lapply(.SD,mean),locus]

#   locus    data1    data2
#1:     1 11.58667 13.58667
#2:     2 14.77500 18.56500
#3:     3 13.02667 10.93333

为方便起见,这里没有评论的全部内容:

library(data.table)
x = fread('data.txt')
cnames = x$V1
x[,V1:=NULL]
x = t(x)
x = data.table(x,keep.rownames=F)
colnames(x) = cnames
x[,exon:=NULL]
x[,lapply(.SD,mean),locus]

答案 1 :(得分:1)

awk '   NR==1{for(i=2;i<NF+1;i++) multi[i]=$i} 
        NR>2{
            for(i in multi)
            {   
                data[multi[i]] = 0 
                count[multi[i]] = 0 
            }   
            for(i=2;i<NF+1;i++) 
            {    
                data[multi[i]] += $i    
                count[multi[i]] += 1
            }; 

            printf "%s ",$1; 
            for(i in data) 
                printf "%s ", data[i]/count[i]; 
            print ""  
        }' <file_name>

<file_name>替换为您的数据文件

答案 2 :(得分:1)

您可以使用GNU datamash版本1.1.0或更新版本(我使用的是上一版本 - 1.1.1):

#!/bin/bash

lines=$(wc -l < "$1")

datamash -W transpose < "$1" |
datamash -H groupby 1 mean 3-"$lines" |
datamash transpose 

用法: mean_value.sh input.txt | column -t(美丽视图需要column -t,没有必要)

<强>输出:

GroupBy(locus)  1                2       3
mean(data1)     11.586666666667  14.775  13.026666666667
mean(data2)     13.586666666667  18.565  10.933333333333