根据共享值对行进行分组

Sorting rows into groups based on shared values

我有一个包含大量行的 CSV,来自用户提交的表单。每行都包含一个用户电子邮件,以及一个用于列出其组中其他用户电子邮件的字段。到目前为止,我已经使用 Python 和 pandas 编写了一个简短的脚本,将 CSV 加载到数据框中并清理条目。

我想按组对行进行排序,但是 运行 遇到了一些概念性问题。由于它是用户输入的,因此列表不一定完整或拼写正确。处理这个问题的最佳方法是什么?我对像这样解析数据完全陌生,而且总体上没有经验。

这里有一些示例数据来说明我的意思:

email,group
user1@a.com, "['user4@b.com','user3@c.com']"
user2@a.com,
user3@c.com, "['user1@a.com']"
user4@b.com, "['user1@a.com','user3@b.com']"

所以这里user1、user3、user4在一个组里。问题是 user3 只列出了 user1.

我的第一个想法是将提交用户的电子邮件附加到组列表,然后对列表进行排序,然后按字母顺序列。但是,这只有在每个人的组条目都完整的情况下才有效。

我不想手动挑选 200 个组,但我不知道如何进行。 这是我目前的伪代码计划:

data # dataframe containing imported CSV
sorted_groups # result dataframe with equivalent rows, but sorted into groups
sort(data) by len(data[group])
for each row in data:
    append row to sorted_groups
    search for rows where email == entry in groups
    append matching rows to sorted_groups
    remove matching rows from data
    remove initial row from data

这肯定会因拼写错误而失败,并且只有在组中至少有一个人正确无误的情况下才会起作用。不过,这是我目前拥有的最好的。

感谢您抽出宝贵时间阅读本文。如果我能澄清任何问题,请告诉我,并指出正确的方向!

我不确定您的数据是如何存储的,所以我写这篇文章时假设您有一个数据行列表,并且每一行都包含在表单中输入的所有电子邮件地址。例如,

rows = [['user1@a.com','user4@b.com','user3@c.com'],
        ['user2@a.com'],
        ['user3@c.com', 'user1@a.com'],
        ['user4@b.com','user1@a.com','user3@b.com']]

我还假设每个用户都属于一个且仅属于一个组,每个用户都提交了表单,并且每个用户都没有拼错他们的电子邮件。

我们可以使用

获取一组有效的电子邮件地址
  valid = {row[0] for row in rows}

我们可以构建一个字典,将用户映射到群组,合并群组,并删除无效电子邮件。

ugDict = {}

for row in rows:
  mergedGroup = set(row) & valid
  for user in row:
    if user in ugDict:
      mergedGroup |= ugDict[user]
  for user in mergedGroup:
    ugDict[user] = mergedGroup

这将导致从用户到组的映射,并将包括任何键入错误的电子邮件地址。您必须决定如何验证电子邮件——您可能只想忽略它们。

现在,要获取组的排序列表,请创建所有组的集合,然后使用排序函数。

sortedGroups = sorted({frozenset(g) for g in ugDict.values()})

frozenset(g) 使 python 的集合对象可散列(即可排序)。

结果?

sortedGroups = [frozenset({'user2@a.com'}),
                frozenset({'user1@a.com', 'user3@b.com', 'user4@b.com'})]