计算包含二进制数的行中的比率值" 0" &安培; " 1"

时间:2015-03-15 03:02:09

标签: awk gawk

我有一个包含超过2000行和45001列​​的数据文件。

第一列实际上是一个解释数据类型的“字符串”。

从第2列开始,直至列#45001,数据被重新命名为

  

“1”

  

“0”

例如,一行中的数据模式为

  

(0 0 0 1 1 0 1 1 1 0 1 1 1 1 0 0 0 1 0 0 1 1 1 0 0)

数据的总数是25.在该数据行中,有5个子组,它们仅由数字“1”组成,例如(11 111 1111 1 111)。子组之间的“0”被假定为“分隔符”。所有“1”的总数是= 13.

我想计算

的比例
  

(所有“1”的总数/仅由“1”组成的子组总数)

那是

  

(13/5)。

我尝试使用此代码计算所有“1”的总和;

awk -F '0' '{print NF}' < inputfile.in

这给出了值13。

但我不知道如何进一步从这里开始计算我想要的比例。 我不知道如何找到每一行内的子组数量,因为“1”和“0”的出现次数是随机的。

希望得到一些帮助来解决这个问题。

提前感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

我从描述中不清楚输入文件的格式是什么。假设输入如下:

$ cat file
0 0 0 1 1 0 1 1 1 0 1 1 1 1 0 0 0 1 0 0 1 1 1 0 0

计算1的数量和1的组数并取其比例:

$ awk '{f=0;s1=0;s2=0;for (i=2;i<=NF;i++){s1+=$i;if ($i && !f)s2++;f=$i}; print s1/s2}' file
2.6

更新:处理全零

假设文件中的一行全部为零:

$ cat file
0 0 0 1 1 0 1 1 1 0 1 1 1 1 0 0 0 1 0 0 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

对于第二行,两个和都为零,这将导致除以零的误差。我们可以通过添加if语句来避免这种情况,该语句将打印比例(如果存在)或0/0不存在:

if (s2>0)print s1/s2; else print s1"/"s2

完整的代码现在是:

$ awk '{f=0;s1=0;s2=0;for (i=2;i<=NF;i++){s1+=$i;if ($i && !f)s2++;f=$i}; if (s2>0)print s1/s2; else print s1"/"s2}' file
2.6
0/0

如何运作

代码使用三个变量。 f是一个标志,如果我们当前在一组1中则为真(1),否则为假(0)。 s1是该行的数量。 s2是该行上的一组数量。

  • f=0;s1=0;s2=0

    在每一行的开头,我们初始化变量。

  • for (i=2;i<=NF;i++){s1+=$i;if ($i && !f)s2++;f=$i}

    我们遍历从字段2开始的行上的每个字段。如果字段包含1,我们递增计数器s1。如果该字段为1并且是新组的开头,我们会增加s2

  • if (s2>0)print s1/s2; else print s1"/"s2}

    如果我们遇到至少一个,我们打印比率s1/s2。否则,我们会打印0/0

答案 1 :(得分:1)

这是awk,可以满足您的需求:

cat file
data 0 0 0 1 1 0 1 1 1 0 1 1 1 1 0 0 0 1 0 0 1 1 1 0 0
data 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
data 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
data 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
BMR_10@O24-BMR_6@O13-H13 1 1 1 1 1 1 1 1 0 1 1 1 1 0 1 1 1 1 1 1 1 0 1 1 1
data 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1

awk '{$1="";$0="0 "$0" 0";t=split($0,b,"1")-1;gsub(/ +/,"");n=split($0,a,"[^1]+")-2;print (n?t/n:0)}' t
2.6
0
25
11
5.5
3