【问题标题】:Delete a column from a tab separated file based on numerical content of column?根据列的数字内容从制表符分隔的文件中删除列?
【发布时间】:2018-08-20 07:58:32
【问题描述】:

我有一个制表符分隔的文件,见下文: 第一列包含位置编号,1-end 其余的都有一些频率数字。

Position     A    B    C    D
1          117    0    1    0   
2            4    0    0   16   
3            0    5   11    0   
4            0    0    0    5   
5            0   15    0    0   
6          100    0  108    0   
7            0    0  147    0  

我想将此文件重新格式化为有两列,第一列是保持原样的位置列,第二列包含每个位置的最高频率。

理想输出:

Position    HighFreq
1                117
2                 16  
3                 11  
4                  5   
5                 15   
6                108  
7                147 

到目前为止,我拥有的是一个选择最高数字并打印的函数:

awk '{max=$1; for(i=2;i<=NF; i++) {if($i>max){max=$i;}};printf"%f\n",max}' file.tsv

我正在尝试为这个问题编写一个 bash 解决方案,但 Perl/Python 是最受欢迎的!

【问题讨论】:

    标签: python bash perl csv


    【解决方案1】:

    由于您选择了 Python 标记,这可以在 Python 中按如下方式完成:

    import sys
    import csv
    
    with open(sys.argv[1], 'rb') as f_input:
        tsv = csv.reader(f_input, delimiter='\t')
        next(tsv)
        data = []
    
        for row in tsv:
            row = map(int, row)
            data.append([row[0]] + [max(row[1:])])
    
    with open(sys.argv[1], 'wb') as f_output:
        tsv = csv.writer(f_output, delimiter='\t')
        tsv.writerow(['Position', 'HighFreq'])
        tsv.writerows(data)
    

    【讨论】:

      【解决方案2】:
      $ perl -MList::Util=max -F/\t/ -lane 'print join "\t", $. == 1 ? qw(Position HighFreq) : ( $F [0], max(@F[1..$#F]) )'
      

      说明

      • -MList::Util=max

        加载List::Util::max

      • -F/\t/ -a

        激活自动拆分并将分隔符设置为/\t/

      • -lne

        自动附加适当的行尾,应用单行,逐行处理ARGV输入

      • print join "\t", ...

        打印制表符分隔

      • $. == 1 ? ... : ...

        处理列标题

      • max( @F[1..$#F] )

        返回@F 的所有非第一个元素的最大值

      【讨论】:

      • 将自己局限在单线的丑陋中似乎是迟钝的。除非您确定不再需要此功能,否则您将不得不在非常无情的环境中一次又一次地完成编码过程。
      【解决方案3】:
      awk 'BEGIN{print"Position\tHighFreq"}{if(NR==1)next; max=0;for(i=2;i<=NF; i++) {if($i>max){max=$i;}} printf"%d\t%d\n",$1,max;}' file.tsv
      

      输出:

      Position    HighFreq
      1   117
      2   16
      3   11
      4   5
      5   15
      6   108
      7   147
      

      【讨论】:

        【解决方案4】:

        在 Perl 中

        use strict;
        use warnings 'all';
        use feature 'say';
        use autodie;
        
        use List::Util 'max';
        
        open my $fh, '<', 'freq.txt';
        
        <$fh>;
        say join "\t", qw/ Position HighFreq /;
        
        while ( <$fh> ) {
            my ($n, @fields) = split;
            say join "\t", $n, max(@fields);
        }
        

        输出

        Position    HighFreq
        1   117
        2   16
        3   11
        4   5
        5   15
        6   108
        7   147
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-08
          • 1970-01-01
          • 2018-03-06
          • 2013-01-21
          • 2020-07-18
          相关资源
          最近更新 更多