【问题标题】:python position frequency dictionary of letters in words单词中字母的python位置频率词典
【发布时间】:2017-09-27 07:53:20
【问题描述】:

为了有效地获取字母的频率(给定字母表 ABC 在字典中的字符串 code 我可以制作一个函数 a-la (Python 3):

def freq(code):
   return{n: code.count(n)/float(len(code)) for n in 'ABC'}

然后

code='ABBBC'   
freq(code)

给我

{'A': 0.2, 'C': 0.2, 'B': 0.6}

但是我怎样才能得到不等长度字符串列表中每个位置的频率呢?例如mcode=['AAB', 'AA', 'ABC', ''] 应该给我一个嵌套结构,如字典列表(其中每个字典是每个位置的频率):

[{'A': 1.0, 'C': 0.0, 'B': 0.0}, 
 {'A': 0.66, 'C': 0.0, 'B': 0.33},
 {'A': 0.0, 'C': 0.5, 'B': 0.5}]

我无法弄清楚如何在所有字符串中计算每个位置的频率,并将其包装在列表理解中。受到其他 SO 字数统计的启发,例如讨论得很好的帖子Python: count frequency of words in a list 我相信collections 的计数器模块可能会有所帮助。

这样理解 - 将 mcode 字符串写在不同的行上:

AAB
AA
ABC

那么我需要的是 dict 列表中字母 ABC 的按列频率(AAA、AAB、BC),其中每个列表元素是每列 ABC 的频率。

【问题讨论】:

  • 我不太明白你的例子。第一个字符串 'AAB' 的输出应该是 {'A': 0.66, 'C': 0.0, 'B': 0.33}?此外,您的字符串 (ABC) 中是否总是最多有 3 个不同的字母?
  • 频率中的第一个位置是在 AAA 上计算的,在位置 2 它的 AAB 在位置 3 的 BC 上。那有意义吗 ?在单独的行上对齐单词,然后沿列查找频率。
  • 您可以使用itertools.zip_longest(*mcode) 并在此循环上使用您的freq。不过,您必须更改 len(code) 以反映正确的长度。
  • 顺便说一句:在 Python 3 中,您不需要 float()
  • @Allen 你现在明白了吗? - 查看我的更新(我写的是每个位置的频率)

标签: python dictionary list-comprehension frequency letter


【解决方案1】:

一个更短的解决方案:

from itertools import zip_longest

def freq(code):
    l = len(code) - code.count(None)
    return {n: code.count(n)/l for n in 'ABC'}

mcode=['AAB', 'AA', 'ABC', '']
results = [ freq(code) for code in zip_longest(*mcode) ]
print(results)

【讨论】:

  • 太好了——我总是忘记 itertools
【解决方案2】:

例如,这些步骤在 cmets 中进行了简要说明。不使用模块collectionsCounter,因为位置的映射还包含字符,这些字符不存在于该位置并且频率的顺序似乎无关紧要。

def freq(*words):
    # All dictionaries contain all characters as keys, even
    # if a characters is not present at a position.
    # Create a sorted list of characters in chars.
    chars = set()
    for word in words:
        chars |= set(word)

    chars = sorted(chars)

    # Get the number of positions.
    max_position = max(len(word) for word in words)

    # Initialize the result list of dictionaries.
    result = [
        dict((char, 0) for char in chars)
        for position in range(max_position)
    ]

    # Count characters.
    for word in words:
        for position in range(len(word)):
            result[position][word[position]] += 1

    # Change to frequencies
    for position in range(max_position):
        count = sum(result[position].values())
        for char in chars:
            result[position][char] /= count  # float(count) for Python 2

    return result


# Testing
from pprint import pprint
mcode = ['AAB', 'AA', 'ABC', '']
pprint(freq(*mcode))

结果(Python 3):

[{'A': 1.0, 'B': 0.0, 'C': 0.0},
 {'A': 0.6666666666666666, 'B': 0.3333333333333333, 'C': 0.0},
 {'A': 0.0, 'B': 0.5, 'C': 0.5}]

在 Python 3.6 中,字典甚至是排序的;早期版本可以使用collections 中的OrderedDict 而不是dict

【讨论】:

    【解决方案3】:

    您的代码根本没有效率:

    • 您首先需要定义要计算的字母
    • 您需要为每个不同的字母解析字符串

    你可以使用Counter:

    import itertools
    from collections import Counter
    mcode=['AAB', 'AA', 'ABC', '']
    all_letters = set(''.join(mcode))
    
    def freq(code):
      code = [letter for letter in code if letter is not None]
      n = len(code)
      counter = Counter(code)
      return {letter: counter[letter]/n for letter in all_letters}
    
    print([freq(x) for x in itertools.zip_longest(*mcode)])
    # [{'A': 1.0, 'C': 0.0, 'B': 0.0}, {'A': 0.6666666666666666, 'C': 0.0, 'B': 0.3333333333333333}, {'A': 0.0, 'C': 0.5, 'B': 0.5}]
    

    对于 Python2,您可以使用 itertools.izip_longest

    【讨论】:

      猜你喜欢
      • 2019-02-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-05
      • 1970-01-01
      • 2022-07-16
      • 2020-09-03
      • 2015-01-07
      相关资源
      最近更新 更多