繁体   English   中英

在第二列中查找第一列中选​​择的概率

[英]Find the probability in 2nd column for a selection in 1st column

我有两列如下

ifile.dat
1   10
3   34
1   4
3   32
5   3
2   2
4   20
3   13
4   50
1   40
2   20
5   2

我想计算第一列中某些选择的第二列中的概率。

ofile.dat
1-2   0.417 #Here 1-2 means all values in 1st column ranging from 1 to 2; 
            #0.417 is the probability of corresponding values in 2nd column 
            # i.e. count(10,4,2,40,20)/total = 5/12 
3-4   0.417 #count(34,32,20,13,50)/total = 5/12
5-6   0.167 #count(3,2)/total = 2/12

同样,如果我选择了 3 个数字的选择范围,那么期望的输出将是

ofile.dat
1-3  0.667
4-6  0.333

RavinderSingh13 和 James Brown 给出了不错的脚本(请参阅答案),但这些脚本不适用于第一列中大于 10 的值。

ifile2.txt
10   10
30   34
10   4
30   32
50   3
20   2
40   20
30   13
40   50
10   40
20   20
50   2

~

EDIT2:考虑到 OP 编辑​​过的样本,您可以尝试以下操作吗? 我已经用 OP 的第一个和最新的编辑样本成功地对其进行了测试,并且它们都可以正常工作。

还有一件事,我制作了这个解决方案,这样一个“角落案例”可能会留下打印元素,以防它在最后一行没有跨越范围值。 就像 OP 的第一个示例,其中range=2但最大值为5因此不会在此处留下 5。

sort -n Input_file |
awk -v range="2" '
  !b[$1]++{
    c[++count]=$1
  }
  {
    d[$1]=(d[$1]?d[$1] OFS:"")$2
    tot_element++
    till=$1
  }
  END{
    for(i=1;i<=till;i++){
       num+=split(d[i],array," ")
       if(++j==range){
          start=start?start:1
          printf("%s-%s %.02f\n",start,i,num/tot_element)
          start=i+1
          j=num=""
          delete array
       }
       if(j!="" && i==till){
          printf("%s-%s %.02f\n",start,i,num/tot_element)
       }
    }
  }
'

输出如下。

1-10 0.25
11-20 0.17
21-30 0.25
31-40 0.17
41-50 0.17


编辑:如果您的 Input_file 没有第二列,请尝试以下操作。

sort -k1 Input_file |
awk -v range="1" '
  !b[$1]++{
    c[++count]=$1
  }
  {
    d[$1]=(d[$1]?d[$1] OFS:"")$0
    tot_element++
    till=$1
  }
  END{
    for(i=1;i<=till;i+=(range+1)){
       for(j=i;j<=i+range;j++){
          num=split(d[c[j]],array," ")
          total+=num
       }
       print i"-"i+range,tot_element?total/tot_element:0
       total=num=""
    }
  }
'


您能否尝试使用所示示例进行以下,编写和测试。

sort -k1 Input_file |
awk -v range="1" '
  !b[$1]++{
    c[++count]=$1
  }
  {
    d[$1]=(d[$1]?d[$1] OFS:"")$2
    tot_element++
    till=$1
  }
  END{
    for(i=1;i<=till;i+=(range+1)){
       for(j=i;j<=i+range;j++){
          num=split(d[c[j]],array," ")
          total+=num
       }
       print i"-"i+range,tot_element?total/tot_element:0
       total=num=""
    }
  }
'


如果您不必包含任何0值,请尝试以下操作。

sort -k1 Input_file |
awk -v range="1" '
  !b[$1]++{
    c[++count]=$1
  }
  {
    d[$1]=(d[$1]!=0?d[$1] OFS:"")$2
    tot_element++
    till=$1
  }
  END{
    for(i=1;i<=till;i+=(range+1)){
       for(j=i;j<=i+range;j++){
          num=split(d[c[j]],array," ")
          total+=num
       }
       print i"-"i+range,tot_element?total/tot_element:0
       total=num=""
    }
  }
'

其他:

$ awk '
BEGIN {
    a[1]=a[2]=1                 # define the groups here
    a[3]=a[4]=2                 # others will go to an overflow group 3
}
{
    b[(($1 in a)?a[$1]:3)]++    # group 3 defined here
}
END {                           # in the end
    for(i in b)                 # loop all groups in no particular order
        print i,b[i]/NR         # and output
}' file

输出

1 0.416667
2 0.416667
3 0.166667

更新 另一个带有范围配置文件的 awk。 $1 是范围的开始,$2 是结束,$3 是组名:

1 3 1-3
4 9 4-9
10 30 10-30
40 100 40-100

awk程序:

$ awk '
BEGIN {
    OFS="\t"
}
NR==FNR {
    for(i=$1;i<=$2;i++)
        a[i]=$3
    next
}
{
    b[(($1 in a)?a[$1]:"others")]++   # the overflow group is now called "others"
}
END {
    for(i in b)
        print i,b[i]/NR
}' rangefile datafile

将两个数据集连接在一起的输出(以及通过管道传输到sort -n awk 输出):

1-3     0.285714
4-9     0.142857
10-30   0.285714
40-100  0.142857

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM