首页 > 解决方案 > 查找数据框中列的各种值之间的共同交集,其中值是数组/列表

问题描述

我有一个数据框,其前 5 行看起来像这样。

 userID       CategoryID          sectorID
agunii2035  [16, 17, 3, 12, 1]  [2, 33, 29, 18, 23]
agunii3007  [2, 4, 6, 3, 16]    [4, 15, 29, 10, 18]
agunii2006  [8, 16, 2, 5, 12]   [38, 18, 7, 36, 33]
agunii2003  [6, 4, 2, 5, 17]    [37, 12, 3, 32, 34]
agunii3000  [12, 11, 7, 3, 1]   [38, 1, 13, 25, 3]

现在对于任何userID(let say "userID" = 'agunii2035') ,我想获取“userID”,其“ CategoryID”或“ SectorID”至少有一个共同的交集值(例如,因为 agunni2035 和 agunni3007 至少有一个共同的" CategoryID" 即 '16' 或有一个共同的 " sectorID" 即 '29',我们将考虑 " userID" 'agunii3007')

输出可以是一个看起来像这样的数据框

   userID         user_with_common_cat/sectorID
agunii2035      {aguni3007, agunni2006, agunii2003, agunii300}
aguni3007       {agunni2035,agunni2006,agunii2003}

and so on

或者这也可以是

   userID         user_with_common_cat/sectorID
agunii2035      [aguni3007, agunni2006, agunii2003, agunii300]
aguni3007       [agunni2035,agunni2006,agunii2003}

and so on

请问有什么帮助吗?

编辑

到目前为止我做了什么:

userID= 'agunii2035'

common_users = []

for user in uniqueUsers:
    common = list(set(df_interest.loc[df_interest['userID'] == 'agashi2035', 'categoryID'].iloc[0]).intersection(df_interest.loc[df_interest['userID'] == user, 'categoryID'].iloc[0]))
                  
    #intersect = len(common) > 0
                  
    if (len(common) > 0):
            common_users.append(user)

我也想对扇区执行此操作,并为扇区或类别创建交叉点,common_user如果任何交叉点的长度为 1,则附加到列表中。

另外,我想为所有用户执行此操作。

标签: pythonpython-3.xlist

解决方案


我通常不太喜欢操纵dataframe“单元格”包含列表而不是单个元素(float,str等)的位置。

在下文中,我将操作 pythondict而不是dataframe.

数据

您可以使用doc方法将 pandasdataframe转换为。dictto_dict

以下是字典中的数据:

d = {
        "agunii2035": {
            "category_id": [16, 17, 3, 12, 1],
            "sector_id": [2, 33, 29, 18, 23],
        },
        "agunii3007": {
            "category_id": [2, 4, 6, 3, 16],
            "sector_id": [4, 15, 29, 10, 18],
        },
        "agunii2006": {
            "category_id": [8, 16, 2, 5, 12],
            "sector_id": [38, 18, 7, 36, 33],
        },
        "agunii2003": {
            "category_id": [6, 4, 2, 5, 17],
            "sector_id": [37, 12, 3, 32, 34],
        },
        "agunii3000": {
            "category_id": [12, 11, 7, 3, 1],
            "sector_id": [38, 1, 13, 25, 3],
        },
    }

解决方案 1:使用 for 循环遍历字典

在这里,我们可以有两个 for 循环来检查所有元素。唯一要知道的是如何list在 python 中将两个与set.

results = {}
for user_a, category_sector_a in d.items():
    results[user_a] = []
    for user_b, category_sector_b in d.items():
        if user_a != user_b:
            # we use "set" to have common elements between the two lists
            intersection_category = set(category_sector_a["category_id"]) & set(
                category_sector_a["category_id"]
            )
            intersection_sector = set(category_sector_a["sector_id"]) & set(
                category_sector_a["sector_id"]
            )
            if (len(intersection_category)) > 0 or (len(intersection_category) > 0):
                results[user_a].append(user_b)

解决方案2:itertools

在这里,我们itertools用来生成keys原始数据中的所有组合。这将使我们避免这两种情况for loops

import itertools

results = {}
for user_a, user_b in itertools.combinations(d.keys(), 2):
    # we use "set" to have common elements between the two lists
    intersection_category = set(d[user_a]["category_id"]) & set(
        d[user_b]["category_id"]
    )
    intersection_sector = set(d[user_a]["sector_id"]) & set(d[user_b]["sector_id"])
    if (len(intersection_category)) > 0 or (len(intersection_category) > 0):
        if user_a in results:
            results[user_a].append(user_b)
        else:
            results[user_a] = [user_b]

这几乎和以前一样。除了,如果不存在,最后我们必须keyresults字典中创建。key

解决方案 3:itertools 和列表理解

在这里,我们也使用了 itertools,但在list理解中。我们使用理解来仅输出符合条件(部分)list的用户对。if

import operator
import itertools

results = [
    (user_a, user_b)
    for user_a, user_b in itertools.combinations(d.keys(), 2)
    if (len(set(d[user_a]["category_id"]) & set(d[user_b]["category_id"]))) > 0
    or (len(set(d[user_a]["sector_id"]) & set(d[user_b]["sector_id"])) > 0)
]
results = {
    k: list(list(zip(*g))[1])
    for k, g in itertools.groupby(results, operator.itemgetter(0))
}

注意最后我们需要的部分,groupy因为理解的输出list是用户元组(对)的列表。groupypython中元组列表的解决方案来自SO上的这个解决方案。


推荐阅读