python - 查找数据框中列的各种值之间的共同交集,其中值是数组/列表
问题描述
我有一个数据框,其前 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,则附加到列表中。
另外,我想为所有用户执行此操作。
解决方案
我通常不太喜欢操纵dataframe
“单元格”包含列表而不是单个元素(float
,str
等)的位置。
在下文中,我将操作 pythondict
而不是dataframe
.
数据
您可以使用doc方法将 pandasdataframe
转换为。dict
to_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]
这几乎和以前一样。除了,如果不存在,最后我们必须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
是用户元组(对)的列表。groupy
python中元组列表的解决方案来自SO上的这个解决方案。
推荐阅读
- terraform - 如何使用 terraform 将 Azure 应用服务主体 ID 传递给 SQL Server
- angularjs - 获取过滤的 angularJS 表的当前行数
- c# - Linux 对端口“ttyUSB0”的访问被拒绝通过 .Net5,即使是 root
- unity3d - 如何实例化预制件并使用 PHOTON 设置其依赖项
- telegram - 从组 ID 获取 Telegram 组链接/用户名
- ffmpeg - 如何使用 ffmpeg 将 .srt 文件转换为基于 ttml 的 xml 字幕文件?
- react-native - 如何在一个主平面列表中显示一个子平面列表?
- python - 如何使用 object_detector.EfficientDetLite4Spec tensorflow lite 继续使用检查点进行训练
- r - 在 R 中生成图形时如何调整问题
- vb.net - 部分解决 - Visual Studio 2019 正在发布两个文件夹,其中包含两个几乎相同的 EXE,并链接到错误的文件夹