Python 基于另一列查找公共列值
我有一个数据框,它包含两列UserId和movieId。不同的用户观看了不同的电影。我想获取两个普通用户之间的三部普通电影Python 基于另一列查找公共列值,python,pandas,data-science,Python,Pandas,Data Science,我有一个数据框,它包含两列UserId和movieId。不同的用户观看了不同的电影。我想获取两个普通用户之间的三部普通电影 df = DataFrame({'userId' : [1,2,3,1,3,6,2,4,1,2], 'movieId' : [222,222,900,555,555,888,555,222,666,666]}) 所需的结果应该是这样的 userId movieId 1 222 1 555 1 666 2 222 2
df = DataFrame({'userId' : [1,2,3,1,3,6,2,4,1,2], 'movieId' : [222,222,900,555,555,888,555,222,666,666]})
所需的结果应该是这样的
userId movieId
1 222
1 555
1 666
2 222
2 555
2 666
我不需要其他不包含三个用户常见电影的条目。例如,如果有另一个用户观看了所有三部电影,则应考虑。通过创建指标,然后通过最大值为每个用户获取1个值,并通过sum和过滤具有N个公共值的行,最后通过重塑多索引并通过以下方式将多索引转换为列:
对于测试,只有2个用户可以使用另一个具有pivot_table和dropna的解决方案:
按创建指标,然后按最大值为每个用户获取1个值,并按sum和筛选具有N个公共值的行,最后按重塑多索引并将其转换为列:
对于测试,只有2个用户可以使用另一个具有pivot_table和dropna的解决方案:
我认为最好是定义一个函数来获取两个用户u和v之间的k个公共电影,例如:
def common_movies(d, u, v, k=3):
"""Fetch common movies between users u and v"""
# create filter by the specified users
mask = d['userId'].isin((u, v))
# group by movieId, aggregate into a list and then explode on userId
values = d[mask].groupby('movieId').agg({'userId': list}).explode('userId')
# filter by the first k movies
return values.loc[values.index.unique()[:k]].sort_values('userId').reset_index()
print(common_movies(df, 1, 2))
输出
请注意,在上述函数中,默认值为3,正如指定的那样,该函数也很健壮,因为如果没有指定值的数量,该函数将不会失败,例如,如果删除该函数,它将返回:
movieId userId
0 555 1
1 666 1
2 555 2
3 666 2
我认为最好是定义一个函数来获取两个用户u和v之间的k个公共电影,例如:
def common_movies(d, u, v, k=3):
"""Fetch common movies between users u and v"""
# create filter by the specified users
mask = d['userId'].isin((u, v))
# group by movieId, aggregate into a list and then explode on userId
values = d[mask].groupby('movieId').agg({'userId': list}).explode('userId')
# filter by the first k movies
return values.loc[values.index.unique()[:k]].sort_values('userId').reset_index()
print(common_movies(df, 1, 2))
输出
请注意,在上述函数中,默认值为3,正如指定的那样,该函数也很健壮,因为如果没有指定值的数量,该函数将不会失败,例如,如果删除该函数,它将返回:
movieId userId
0 555 1
1 666 1
2 555 2
3 666 2
这里有一个做一些数据帧操作的 设置一些变量: 普通电影=3部 n_用户=2 创建包含电影组的列: df1=df.groupby'userId'['movieId'].applylist.reset\u indexname='movies' 输出:
df1
userId movies
0 1 [222, 555, 666]
1 2 [222, 555, 666]
2 3 [900, 555]
3 4 [222]
4 6 [888]
df2
userId movies
0 1 [222, 555, 666]
1 2 [222, 555, 666]
df3
userId movies
0 1 222
0 1 555
0 1 666
1 2 222
1 2 555
1 2 666
df4
movies viewer_count
0 222 2
1 555 2
2 666 2
将该列表减少到与普通电影相同的电影数量,因为这是我们想要的总数。如果这一点没有得到满足,那么我们可以跳过剩下的过程
df2=df1.loc[df1['movies'].applylambda x:lenx==n_common_movies,:]
输出:
df1
userId movies
0 1 [222, 555, 666]
1 2 [222, 555, 666]
2 3 [900, 555]
3 4 [222]
4 6 [888]
df2
userId movies
0 1 [222, 555, 666]
1 2 [222, 555, 666]
df3
userId movies
0 1 222
0 1 555
0 1 666
1 2 222
1 2 555
1 2 666
df4
movies viewer_count
0 222 2
1 555 2
2 666 2
使用pd.explode堆叠步骤2的结果:
df3=df2.分解“电影”
输出:
df1
userId movies
0 1 [222, 555, 666]
1 2 [222, 555, 666]
2 3 [900, 555]
3 4 [222]
4 6 [888]
df2
userId movies
0 1 [222, 555, 666]
1 2 [222, 555, 666]
df3
userId movies
0 1 222
0 1 555
0 1 666
1 2 222
1 2 555
1 2 666
df4
movies viewer_count
0 222 2
1 555 2
2 666 2
创建另一个分组以获取每部电影的观看次数:
df4=df3.groupby'movies'.size.reset\u indexname='viewer\u count'
输出:
df1
userId movies
0 1 [222, 555, 666]
1 2 [222, 555, 666]
2 3 [900, 555]
3 4 [222]
4 6 [888]
df2
userId movies
0 1 [222, 555, 666]
1 2 [222, 555, 666]
df3
userId movies
0 1 222
0 1 555
0 1 666
1 2 222
1 2 555
1 2 666
df4
movies viewer_count
0 222 2
1 555 2
2 666 2
最后,检查基于预期用户数的过滤结果是否等于普通电影数的长度,并打印…userId,我猜。打印你想要的任何东西,哈哈
如果lendf4[df4['viewer\u count']==n\u用户]==n\u公共:
tmp='\n\t'.加入[listsetdf3['userId']中i的stri]
打印“具有三个常用电影的用户:\n\t{}”.formattmp
输出:
df1
userId movies
0 1 [222, 555, 666]
1 2 [222, 555, 666]
2 3 [900, 555]
3 4 [222]
4 6 [888]
df2
userId movies
0 1 [222, 555, 666]
1 2 [222, 555, 666]
df3
userId movies
0 1 222
0 1 555
0 1 666
1 2 222
1 2 555
1 2 666
df4
movies viewer_count
0 222 2
1 555 2
2 666 2
拥有三部常见电影的用户:
1.
2这里有一个做一些数据帧操作的 设置一些变量: 普通电影=3部 n_用户=2 创建包含电影组的列: df1=df.groupby'userId'['movieId'].applylist.reset\u indexname='movies' 输出:
df1
userId movies
0 1 [222, 555, 666]
1 2 [222, 555, 666]
2 3 [900, 555]
3 4 [222]
4 6 [888]
df2
userId movies
0 1 [222, 555, 666]
1 2 [222, 555, 666]
df3
userId movies
0 1 222
0 1 555
0 1 666
1 2 222
1 2 555
1 2 666
df4
movies viewer_count
0 222 2
1 555 2
2 666 2
将该列表减少到与普通电影相同的电影数量,因为这是我们想要的总数。如果这一点没有得到满足,那么我们可以跳过剩下的过程
df2=df1.loc[df1['movies'].applylambda x:lenx==n_common_movies,:]
输出:
df1
userId movies
0 1 [222, 555, 666]
1 2 [222, 555, 666]
2 3 [900, 555]
3 4 [222]
4 6 [888]
df2
userId movies
0 1 [222, 555, 666]
1 2 [222, 555, 666]
df3
userId movies
0 1 222
0 1 555
0 1 666
1 2 222
1 2 555
1 2 666
df4
movies viewer_count
0 222 2
1 555 2
2 666 2
使用pd.explode堆叠步骤2的结果:
df3=df2.分解“电影”
输出:
df1
userId movies
0 1 [222, 555, 666]
1 2 [222, 555, 666]
2 3 [900, 555]
3 4 [222]
4 6 [888]
df2
userId movies
0 1 [222, 555, 666]
1 2 [222, 555, 666]
df3
userId movies
0 1 222
0 1 555
0 1 666
1 2 222
1 2 555
1 2 666
df4
movies viewer_count
0 222 2
1 555 2
2 666 2
创建另一个分组以获取每部电影的观看次数:
df4=df3.groupby'movies'.size.reset\u indexname='viewer\u count'
输出:
df1
userId movies
0 1 [222, 555, 666]
1 2 [222, 555, 666]
2 3 [900, 555]
3 4 [222]
4 6 [888]
df2
userId movies
0 1 [222, 555, 666]
1 2 [222, 555, 666]
df3
userId movies
0 1 222
0 1 555
0 1 666
1 2 222
1 2 555
1 2 666
df4
movies viewer_count
0 222 2
1 555 2
2 666 2
最后,检查基于预期用户数的过滤结果是否等于普通电影数的长度,并打印…userId,我猜。打印你想要的任何东西,哈哈
如果lendf4[df4['viewer\u count']==n\u用户]==n\u公共:
tmp='\n\t'.加入[listsetdf3['userId']中i的stri]
打印“具有三个常用电影的用户:\n\t{}”.formattmp
输出:
df1
userId movies
0 1 [222, 555, 666]
1 2 [222, 555, 666]
2 3 [900, 555]
3 4 [222]
4 6 [888]
df2
userId movies
0 1 [222, 555, 666]
1 2 [222, 555, 666]
df3
userId movies
0 1 222
0 1 555
0 1 666
1 2 222
1 2 555
1 2 666
df4
movies viewer_count
0 222 2
1 555 2
2 666 2
拥有三部常见电影的用户:
1.
2请求的参数具体是什么?你会提供与之匹配的电影数量吗?要匹配的最少电影数?我将使用一个dict,其中userId作为键,movieId作为值。然后你需要考虑成对的用户,计算他们的电影的交叉点。如果结果的大小高于阈值,则您找到了一个结果。请求的参数具体是什么?你会提供与之匹配的电影数量吗?要匹配的最少电影数?我将使用一个dict,其中userId作为键,movieId作为值。然后你需要考虑成对的用户,计算他们的电影的交叉点。如果结果的大小高于阈值,则发现一个结果。AttributeError:“DataFrame”对象没有Attribute
爆炸。我发现了这个错误。你用的是什么版本的熊猫?请参见在0.25AttributeError之前分解数据帧的步骤:“数据帧”对象没有属性“分解”。我发现了这个错误。你用的是什么版本的熊猫?请参阅在pandas 0.25I具有与这两列对应的其他列之前分解数据帧。我如何获取这些列的数据。@muhammadsanwal-然后使用df1=df。删除重复项['userId','movieId']。我的意思是,我还有其他列,例如评级,时间戳。在完成上述所有过程后,我希望这些列的值带有df1。@muhammadsanwal-是的,如果通过df删除原始数据中的重复项。从我的解决方案中删除重复项['userId','movieId',并合并df1获取所有列,如果需要,还可以使用重复行使用df1=df。合并df1我正在获取,例如,对于两个随机用户,5个常见的电影。如果df1的长度!=电影的长度*用户的长度它应该再次找到其他随机用户。对于某些迭代,它工作正常,然后我得到这个错误indexer:list索引超出范围。回溯之后,错误似乎出现在这一行。重命名axis'movieId',axis=1。你能帮忙吗?我还有其他的栏目和这两个栏目相对应。我如何获取这些列的数据。@muhammadsanwal-然后使用df1=df。删除重复项['userId','movieId']。我的意思是,我还有其他列,例如评级,时间戳。在完成上述所有过程后,我希望这些列的值带有df1。@muhammadsanwal-是的,如果通过df删除原始数据中的重复项。从我的解决方案中删除重复项['userId','movieId',并合并df1获取所有列,如果需要,还可以使用重复行使用df1=df。合并df1我正在获取,例如,对于两个随机用户,5个常见的电影。如果df1的长度!=电影的长度*用户的长度它应该再次找到其他随机用户。对于某些迭代,它工作正常,然后我得到这个错误indexer:list索引超出范围。回溯之后,错误似乎出现在这一行。重命名axis'movieId',axis=1。你能帮忙吗?