gpt4 book ai didi

excel - Python 与 Itertools?

转载 作者:行者123 更新时间:2023-12-01 22:49:30 27 4
gpt4 key购买 nike

我有一个 .csv,其中包含 3 列。人物 X、人物 Y 和人物 Z。有 7000 行名称和不同的组合。我的目标是看看哪对和 3 人一组的匹配度最高。我一直无法在 Excel 中找到可以实现此目标的公式。我确信 python 能够与 itertools 组合,但我还没有那么先进。名字可以按任何顺序排列,只是想看看这 2 或 3 个人在同一排出现了多少次。任何建议都会有很大的帮助,谢谢!

数据小示例

PersonX         PersonY             PersonZ
Aaron Ekblad Keith Yandle Vincent Trocheck
Aaron Ekblad Denis Malgin Mike Matheson
Aaron Ekblad Denis Malgin Mike Matheson
Aaron Ekblad Jonathan Huberdeau Keith Yandle
Aaron Ekblad Jonathan Huberdeau Keith Yandle
Aaron Ekblad Jamie McGinn Keith Yandle
Aaron Ekblad Aleksander Barkov Jonathan Huberdeau
Aaron Ekblad
Adam Erne Andrej Sustr Vladislav Namestnikov
Adam Erne Anthony Cirelli
Adam Erne
Adam Henrique Rickard Rakell Ryan Getzlaf
Adam Henrique Brandon Montour Ryan Getzlaf
Adam Henrique Corey Perry Brandon Montour
Adam Henrique Corey Perry Brandon Montour
Adam Henrique Brian Gibbons Andy Greene
Adam Henrique Ryan Getzlaf
Adam Henrique Ondrej Kase
Adam Henrique Josh Manson
Adam Henrique Brian Gibbons
Adam Henrique
Adam Henrique

启动脚本

import csv
from itertools import combinations, product

#Header = PersonX PersonY PersonZ

#Import Game
with open('1718_All_Goals_&_Assists.csv', newline='') as f:
next(f)
skaters = '\n'.join(' '.join(row) for row in csv.reader(f))
print(skaters)

最佳答案

您可以简单地在 csv.reader 上使用 collections.Counter:

from collections import Counter

>>> cnt = Counter(frozenset(item.strip() for item in line if item.strip()) for line in csv.reader(f))

您可以使用 Counter 的 .most_common 方法获得排序(降序)的输出:

>>> cnt.most_common()
[(frozenset({'Aaron Ekblad', 'Denis Malgin', 'Mike Matheson'}), 2),
(frozenset({'Aaron Ekblad', 'Jonathan Huberdeau', 'Keith Yandle'}), 2),
(frozenset({'Adam Henrique', 'Brandon Montour', 'Corey Perry'}), 2),
(frozenset({'Adam Henrique'}), 2),
(frozenset({'Aaron Ekblad', 'Keith Yandle', 'Vincent Trocheck'}), 1),
(frozenset({'Aaron Ekblad', 'Jamie McGinn', 'Keith Yandle'}), 1),
(frozenset({'Aaron Ekblad', 'Aleksander Barkov', 'Jonathan Huberdeau'}), 1),
(frozenset({'Aaron Ekblad'}), 1),
(frozenset({'Adam Erne', 'Andrej Sustr', 'Vladislav Namestnikov'}), 1),
(frozenset({'Adam Erne', 'Anthony Cirelli'}), 1),
(frozenset({'Adam Erne'}), 1),
(frozenset({'Adam Henrique', 'Rickard Rakell', 'Ryan Getzlaf'}), 1),
(frozenset({'Adam Henrique', 'Brandon Montour', 'Ryan Getzlaf'}), 1),
(frozenset({'Adam Henrique', 'Andy Greene', 'Brian Gibbons'}), 1),
(frozenset({'Adam Henrique', 'Ryan Getzlaf'}), 1),
(frozenset({'Adam Henrique', 'Ondrej Kase'}), 1),
(frozenset({'Adam Henrique', 'Josh Manson'}), 1),
(frozenset({'Adam Henrique', 'Brian Gibbons'}), 1)]

同样,您可以使用以下方法获得最常见的结果(如果出现平局,它将仅返回其中之一):

>>> cnt.most_common(1)
[(frozenset({'Aaron Ekblad', 'Denis Malgin', 'Mike Matheson'}), 2)]

如果您想要所有具有最大计数的内容,您可以使用使用 max 的自定义方法:

>>> maximum_occurences = max(cnt.values())
>>> [group for group, occurences in cnt.items() if occurences == maximum_occurences]
[frozenset({'Aaron Ekblad', 'Denis Malgin', 'Mike Matheson'}),
frozenset({'Aaron Ekblad', 'Jonathan Huberdeau', 'Keith Yandle'}),
frozenset({'Adam Henrique', 'Brandon Montour', 'Corey Perry'}),
frozenset({'Adam Henrique'})]

添加更多说明:

Counter 只是对元素进行计数,这应该正是您想要的 - 但要计数的值必须是可散列的。这很不方便,因为 csv.reader 将返回列表(不方便,因为列表不可散列),因此您需要另一个数据结构。

元组会浮现在脑海中,但是因为您说过名称可以按任何顺序排列,所以您可能需要一个无序的集合。这意味着您应该使用frozenset。但有一个警告:它不能多次保存相同的值,所以如果你有同名的人,你就不能使用它。

我不知道您的 csv 的结构如何,因此结果可能包含空“列”或名称前后的空格,这就是我过滤空元素并删除名称的原因:

item.strip() for item in line if item.strip()

在将其传递给frozenset之前。

如果您不喜欢它剥离两次,您可以添加另一个理解或map:

frozenset(item for item in (item.strip() for item in line) if item)
frozenset(item for item in map(lambda x: x.strip(), line) if item)
frozenset(item for item in map(str.strip, line) if item) # if all items are really of type str

顺便说一句,外部理解可以用 filter 替换为 bool:

frozenset(filter(bool, map(str.strip, line)))

哦,“函数式编程”的奇迹。我什至没有使用过itertools

我完全忘记了:如果您想省略单人组,您可以在访问 most_common 组之前轻松过滤 Counter:

cnt = Counter({k: v for k, v in cnt.items() if len(k) > 1})

这可以在之后应用,或者您可以尝试将其放入 Counter 内的理解中,但我会将其作为练习留给感兴趣的读者。

<小时/>

万一您可能在一行中多次使用相同的名称,并且您不想丢失该“信息”,您可以计算每一行中的名称,然后将该计数器转换为一个元组已统计。

Counter(tuple(Counter(filter(bool, map(str.strip, line))).most_common()) for line in csv.reader(f))

我希望我的俏皮话没有说得太过分。

关于excel - Python 与 Itertools?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49806165/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com