计算bash中第一列中具有相同条目的行数

时间:2016-06-10 19:55:36

标签: bash perl shell stata

我有一个如下所示的数据文件:

123456, 1623326
123456, 2346525
123457, 2435466
123458, 2564252
123456, 2435145

第一列是“ID” - 一个字符串变量。第二栏对我来说无关紧要。我想最终得到

123456, 3
123457, 1
123458, 1

其中第二列现在计算原始文件中与第一列中唯一“ID”对应的条目数。

bash或perl中的任何解决方案都会很棒。即使Stata也会很好,但我认为这在Stata中更难做到。如果有任何不清楚的地方,请告诉我。

9 个答案:

答案 0 :(得分:6)

在Stata中,这只是

contract ID 

答案 1 :(得分:5)

cut -d',' -f1 in.txt | sort | uniq -c | awk '{print $2 ", " $1}'

给出:

123456, 3
123457, 1
123458, 1

答案 2 :(得分:3)

将第一个字段中的数字拆分并将其用作哈希键,每次增加其计数

use warnings;
use strict;

my $file = 'data_cnt.txt';
open my $fh, '<', $file or die "Can't open $file: $!";

my %cnt;
while (<$fh>) {
    $cnt{(/^(\d+)/)[0]}++;
}

print "$_, $cnt{$_}\n" for keys %cnt;

正则表达式在一行的开头捕获连续的数字。当它作为列表返回时,我们将其编入索引以获取用作哈希键的数字(/.../)[0]。当第一次看到一个数字时,它会作为键添加到哈希值,并且由于++,其值设置为1。当看到已作为键存在的数字时,其值将增加++。这是一个典型的频率计数器。

将您的号码放在档案data_cnt.txt中,此输出

123457, 1
123456, 3
123458, 1

如果需要,可以按哈希值对输出进行排序

say "$_, $cnt{$_}" for sort { $cnt{$b} <=> $cnt{$a} } (keys %cnt);

打印

123456, 3
123457, 1
123458, 1

如果出于某种原因,这可以适合单线,

perl -nE '
    $cnt{(/^(\d+)/)[0]}++; 
    }{ say "$_, $cnt{$_}" for sort { $cnt{$b} <=> $cnt{$a} } keys %cnt
' data_cnt.txt

应在终端输入一行。 }{END { }块的缩写。代码与上面的简短脚本相同。 -E-e相同,但启用了功能say

答案 3 :(得分:3)

这会计算前六个字符相同的行数:

$ sort file | uniq -c -w6
      3 123456, 1623326
      1 123457, 2435466
      1 123458, 2564252

文档

来自man uniq

  

-w, - check-chars = N
  在行中比较不超过N个字符

答案 4 :(得分:2)

您可以使用awk:

awk 'BEGIN{FS=OFS=", "} counts[$1]++{} END{for (i in counts) print i, counts[i]}' file

123456, 3
123457, 1
123458, 1
  • FS=OFS=", "设置输入&amp;输出字段分隔符为", "
  • counts[$1]++{}为每个实例递增counts数组1中第一列存储的计数器。 {}同样无所事事
  • END块中,我们遍历counts数组并打印每个唯一idcount

答案 5 :(得分:2)

cutsortuniqsed版本

cut -d',' -f1 | sort | uniq -c | sed 's/^ *\([^ ]*\) \(.*\)/\2, \1/'

或简单的Perl版本,按第一列排序

perl -F',' -anE'$s{$F[0]}++}{say"$_, $s{$_}"for sort keys%s'

或按计数降序排序,然后按第一列排序

perl -F',' -anE'$s{$F[0]}++}{say"$_, $s{$_}"for sort{$s{$b}<=>$s{$a}or$a cmp$b}keys%s'

或按顺序排列哪个键

perl -F',' -anE'push@a,$F[0]if!$s{$F[0]}++}{say"$_, $s{$_}"for@a'

或仅以伪随机顺序

perl -F',' -anE'$s{$F[0]}++}{say"$_, $s{$_}"for keys%s'

等等。

答案 6 :(得分:1)

Perl one-liner:

perl -naE '$h{$F[0]}++}{for(sort keys %h){say "$_ $h{$_}"}' file.txt

123456, 3
123457, 1
123458, 1

-n遍历文件中的每一行

-a在空白处拆分每一行,并用每个条目填充@F数组

}{表示END块,它允许我们在处理完文件中的所有行后迭代哈希

答案 7 :(得分:0)

在Perl中

$ perl -MData::Dump -ne "++@n{/(\d+)/}; END {dd \%n}" data.txt
{ 123456 => 3, 123457 => 1, 123458 => 1 }

答案 8 :(得分:0)

使用datamash

datamash -W -s -g1 count 1 < data

输出:

123456, 3
123457, 1
123458, 1