【问题标题】:Finding common intersection between various values of a columns in a dataframe where values are array/list查找数据框中列的各种值之间的共同交集,其中值是数组/列表
【发布时间】:2020-10-16 06:49:53
【问题描述】:

我有一个数据框,其前 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 (比如说 "userID" = 'agunii2035') ,我想获取 "CategoryID" 或 "SectorID" 具有至少一个公共交集值的 "userID" (例如,由于 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)

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

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

【问题讨论】:

  • 到目前为止你有什么尝试?
  • 我刚刚为单个用户做了一个静态的。 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) 我也想添加扇区部分,并为所有用户执行此操作。

标签: python python-3.x list


【解决方案1】:

我通常不太喜欢操纵dataframe,其中“单元格”包含一个列表而不是单个元素(floatstr 等)。

下面我将操作 python dict 而不是 dataframe

数据

您可以使用to_dict 方法doc 将熊猫dataframe 转换为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 循环来检查所有元素。唯一需要知道的是如何在 python 中将两个listset 相交。

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来生成原始数据中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]

这几乎和以前一样。除非,如果key 不存在,最后我们必须在results 字典中创建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 理解的输出是用户元组(对)的列表。 python中groupy元组列表的解决方案来自this solution on SO。

【讨论】:

  • 非常感谢!我做了解决方案 1。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-23
  • 2017-11-22
  • 2010-10-20
  • 1970-01-01
  • 2022-06-16
  • 1970-01-01
相关资源
最近更新 更多