Skip to main content
 首页 » 编程设计

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

2025年05月04日12lyj

我有一个文本文件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 

期望的输出应该是:

english<tab>walawala<tab>0.1666 
foo bar<tab>laa war<tab>0.5 
hello world<tab>walo lorl<tab>0.3333 

新列是行数除以总行数。

目前我正在这样做:

cat test.in | uniq -c | awk '{print $2"\t"$3"\t"$1}' > test.out 

但这只给我行数而不是概率。另外,我的文件非常大,大约 1,000,000,000 行,每列至少 20 个字符。

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

有没有一样快的 pythonic 解决方案?

请您参考如下方法:

请注意,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)) 

这个脚本输出

english<tab>walawala<tab>0.1667 
foo bar<tab>laa war<tab>0.5000 
hello world<tab>walo lorl<tab>0.3333 

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


但是,如果您只需要合并连续的行,例如 uniq -c,请注意任何使用 Counter 的解决方案都会给出在中给出的输出你的问题,但是你的 uniq -c 方法不会。 uniq -c 的输出将是:

  1 english<tab>walawala 
  2 foo bar<tab>laa war 
  2 hello world<tab>walo lorl 
  1 foo bar<tab>laa war 

不是

  1 english<tab>walawala 
  3 foo bar<tab>laa war 
  2 hello world<tab>walo lorl 

如果这是您想要的行为,您可以使用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)) 

不同之处在于,如果 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 

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


顺便说一下,这些在所有 Python 2.6 中的工作方式相同。