计算包含二进制数“0”和“1”的行内的比率值

Calculating ratio value within a line which contain binary numbers "0" & "1"

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

第一列实际上是一个"string",它解释了数据类型。

从第 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"s e.g. (11 111 1111 1 111 ). The "0"s in between the subgroups are assumed as "定界符组成。所有“1”的总数为 = 13。

我想计算

的比例

(total of all "1"s / total of number of sub-groups made only by "1"s)

也就是

(13/5).

我尝试使用这段代码来计算所有“1”的总数;

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

这给出了值 13。

但我不知道如何进一步计算我想要的比率。 我不知道如何找到每行中的子组数,因为“1"s and "0”的出现次数是随机的。

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

提前感谢任何帮助。

从描述中我不清楚输入文件的格式是什么。假设输入看起来像:

$ 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),否则为假 (0)。 s1 是线上的个数。 s2是直线上1组的个数

  • 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.

这里有一个 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 '{="";[=11=]="0 "[=11=]" 0";t=split([=11=],b,"1")-1;gsub(/ +/,"");n=split([=11=],a,"[^1]+")-2;print (n?t/n:0)}' t
2.6
0
25
11
5.5
3