在成对列表中查找成对项目的频率

finding frequencies of pair items in a list of pairs

假设我有一长串这种类型的清单:

text = [ ['a', 'b'], ['a', 'd'], ['w', 'a'], ['a', 'b'], ... ]

给定第一个元素,我想构建一个字典来显示第二个元素的计数。例如在上面的特定示例中,我想要这样的东西:

{'a': {'b':2, 'd':1},
 'w': {'a':1}
}

以下是我尝试解决它但未成功的方法。我构建了一个独特的第一元素列表。我们称它为 words 然后:

dic = {}

for word in words:
  inner_dic = {}
  for pair in text:
    if pair[0] == word:
      num = text.count(pair)
      inner_dic[pair[1]] = num
  dic[pair[0]] = inner_dic

我得到了一个明显错误的结果。代码的一个问题是,它多算了对。我不确定如何解决这个问题。

您可以使用 defaultdict combined with a Counter 字典:

from collections import Counter, defaultdict
d = defaultdict(Counter)

text = [ ['a', 'b'], ['a', 'd'], ['w', 'a'], ['a', 'b'] ]

for k, v in text:
    d[k][v] += 1 # for single value
   # d[k].update(v) for multiple values i.e list of words

from pprint import pprint as pp

pp(d)
{'a': Counter({'b': 2, 'd': 1}),
'w': Counter({'a': 1})}

defaultdict 将创建一个新的 key/value 配对,如果键不存在,值为计数器字典,如果键存在,我们只需使用 Counter.update 更新值,这与 dict.update 将增加不覆盖的值。

使用没有导入的普通 dict 我们可以使用 dict.setdefault 这将为每个键创建一个新的字典作为值 k 并设置默认值 0 对于每个子项 v:

d = {}
text = [ ['a', 'b'], ['a', 'd'], ['w', 'a'], ['a', 'b'] ]

for k, v in text:
    d.setdefault(k, {}).setdefault(v,0)
    d[k][v] += 1
pp(d)
{'a': {'b': 2, 'd': 1}, 'w': {'a': 1}}

collections module 可以缩短此类任务的完成时间。

对外部字典使用Counter for the counting part (it is a kind of dictionary that returns 0 for missing values, making it easy to use +=1 for incrementing counts). Use defaultdict(它可以自动为每个"first"前缀创建一个新计数器):

>>> from collections import defaultdict, Counter
>>> d = defaultdict(Counter)
>>> text = [ ['a', 'b'], ['a', 'd'], ['w', 'a'], ['a', 'b']]
>>> for first, second in text:
    d[first][second] += 1

这是使用常规词典的等价物:

text = [ ['a', 'b'], ['a', 'd'], ['w', 'a'], ['a', 'b']]

d = {}
for first, second in text:
    if first not in d:
        d[first] = {}
    inner_dict = d[first]
    if second not in inner_dict:
        inner_dict[second] = 0
    inner_dict[second] += 1

短路径或长路径都可以与 json module 完美配合(Counterdefaultdict 都是种类可以 JSON 编码的字典数)。

希望这对您有所帮助。祝你的文本分析顺利:-)

你应该这样做:

for word in words:
  inner_dic = {}
  for pair in text:
    if pair[0] == word:
      num = text.count(pair)
      inner_dic[pair[1]] = num
  dic[word] = inner_dic

也就是说,你应该做 dic[word] 而不是 dic[pair[0]],这会将 inner_dic 分配给最后一个 pair 检查中的第一个元素,即使pair[0] 不是 word.

text = [ ['a', 'b'], ['a', 'd'], ['w', 'a'], ['a', 'b']]
d = {}
for i in text:
    if d.get(i[0]):
        if d[i[0]].get(i[1]):
            d[i[0]][i[1]] +=1
        else:
            d[i[0]][i[1]] = 1 
    else:
        d[i[0]] = {i[1] : 1}
print d
>>>{'a': {'b': 2, 'd': 1}, 'w': {'a': 1}}

这里有一个使用.setdefault方法的方法:

text = [ ['a', 'b'], ['a', 'd'], ['w', 'a'], ['a', 'b'] ]
result={}
for x, y in text:
    result.setdefault(x, {}).setdefault(y,0)
    result[x][y]+=1

>>> result 
{'a': {'b': 2, 'd': 1}, 'w': {'a': 1}}

不需要外部库。