计算行出现次数除以总行数 - unix/python

alv*_*vas 1 python unix count text-files uniq

我有一个文本文件test.in:

english<tab>walawala
foo bar<tab>laa war
foo bar<tab>laa war
hello world<tab>walo lorl
hello world<tab>walo lorl
foo bar<tab>laa war
Run Code Online (Sandbox Code Playgroud)

期望的输出应该是:

english<tab>walawala<tab>0.1666
foo bar<tab>laa war<tab>0.5
hello world<tab>walo lorl<tab>0.3333
Run Code Online (Sandbox Code Playgroud)

新列是行的计数除以总行数.

目前我这样做:

cat test.in | uniq -c | awk '{print $2"\t"$3"\t"$1}' > test.out
Run Code Online (Sandbox Code Playgroud)

但这只给了我计算线而不是概率.此外,我的文件非常庞大,例如1,000,000,000行,每列至少20个字符.

如何正确快速地获得所需的输出?

是否有一个快速的pythonic解决方案?

Ant*_*ala 7

请注意,uniq只计算重复的行,并且必须先排序才能考虑文件中的所有行.对于sort | uniq -c,使用collections.Counter的以下代码更有效,因为它根本不需要对任何内容进行排序:

from collections import Counter

with open('test.in') as inf:
    counts = sorted(Counter(line.strip('\r\n') for line in inf).items())
    total_lines = float(sum(i[1] for i in counts))
    for line, freq in counts:
         print("{}\t{:.4f}".format(line, freq / total_lines))
Run Code Online (Sandbox Code Playgroud)

这个脚本输出

english<tab>walawala<tab>0.1667
foo bar<tab>laa war<tab>0.5000
hello world<tab>walo lorl<tab>0.3333
Run Code Online (Sandbox Code Playgroud)

对于您的描述中给出的输入.


但是,如果您只需要连续连接,uniq -c请注意,任何使用Counter的解决方案都会给出问题中给出的输出,但您的uniq -c方法不会.输出uniq -c will be:

  1 english<tab>walawala
  2 foo bar<tab>laa war
  2 hello world<tab>walo lorl
  1 foo bar<tab>laa war
Run Code Online (Sandbox Code Playgroud)

  1 english<tab>walawala
  3 foo bar<tab>laa war
  2 hello world<tab>walo lorl
Run Code Online (Sandbox Code Playgroud)

如果这是您想要的行为,您可以使用itertools.groupby:

from itertools import groupby

with open('foo.txt') as inf:
    grouper = groupby(line.strip('\r\n') for line in inf)
    items = [ (k, sum(1 for j in i)) for (k, i) in grouper ]
    total_lines = float(sum(i[1] for i in items))
    for line, freq in items:
        print("{}\t{:.4f}".format(line, freq / total_lines))
Run Code Online (Sandbox Code Playgroud)

不同之处在于,如果test.in按照您的规定获得内容,uniq管道将不会产生您在示例中给出的输出,而是您将获得:

english<tab>walawala<tab>0.1667
foo bar<tab>laa war<tab>0.3333
hello world<tab>walo lorl<tab>0.3333
foo bar<tab>laa war<tab>0.1667
Run Code Online (Sandbox Code Playgroud)

由于这不是您的输入示例所说的,可能是您不能在没有解决问题的uniq情况下使用sort- 然后您需要求助于我的第一个示例,Python肯定比您的Unix命令行更快.


顺便说一句,这些在所有Pythons> 2.6中的工作相同.