【问题标题】:Finding common values across rows of dataframe with a restriction based on values in another column基于另一列中的值的限制在数据帧的行中查找公共值
【发布时间】:2019-02-28 22:40:05
【问题描述】:

给定下面的示例数据框,如何在同一位置找到具有相同兴趣的用户?数据是-

userid   interest    location
 1       [A, B]          Z
 2       [A, C, B]       Y
 3       [B, D]          Z
 4       [A, C]          Y
 5       [A, B, D]       Z

输出应该是-

userid    relativeid  common interest  location
  1          3           [B]              Z
  1          5           [A, B]           Z
  2          4           [A,C]            Y

到目前为止,我为每个位置创建了单独的数据框,如下所示-

userid   interest    location
 1       [A, B]          Z
 3       [B, D]          Z
 5       [A, B, D]       Z

代码-

dictionary = df.set_index('userid')['interest'].map(set).to_dict()
dictionary

out = pd.DataFrame(list(itertools.combinations(df.userid, 2)), columns=['userid', 'relative_id']) 
out['common_interest'] = [list(dictionary[x] & dictionary[y]) for x, y in out.values]
out

但这给了我没有位置列的输出。

userid    relativeid  common interest 
  1          3           [B]              
  1          5           [A, B]

问题: 1)如何修改此代码以获取输出中的位置列? 2) 有没有办法做到这一点,而无需根据位置将原始数据帧拆分为多个数据帧?

【问题讨论】:

  • 3和5有共同的B
  • @Wen-Ben yes 3 和 5 有共同的 B
  • 你能解释一下“在同一地点的共同兴趣”是什么意思吗?您是否只对比较具有相同位置值的用户感兴趣?用户 ID 和位置之间是否存在 1:1 的关系?因为如果它是 1:1,并且您没有将用户 1 和 2 相互比较(例如,位于不同位置的用户),您应该能够通过用户 ID 将位置列合并到最终数据帧中。
  • @AlexK 我有多个用户,他们的兴趣(存储在列表中)和他们的位置(他们居住的国家)。例如,我总共有 10 个用户,5 个来自位置 X,3 个来自位置 Y,2 个来自位置 Z,我想编写一个 python 程序来计算位置 X、Y 和 Z 的用户,然后将每个用户与每个用户进行比较同一位置的其他用户找出他们的共同兴趣。我的代码为每个新位置创建一个新的 df,并将具有相同位置的人聚集在该 df 中。我想在不为每个新位置创建新 df 的情况下执行此操作。

标签: python pandas dictionary combinations itertools


【解决方案1】:

这是一种可能的解决方案。我注意到添加的代码。只是创建了一个额外的字典来保存每个用户 ID 的位置信息,如果用户不共享相同的位置,则删除用户组合的功能,以及使用相同位置字典在末尾创建位置列的行最终数据帧。

import itertools

users_df = pd.DataFrame({'userid':[1,2,3,4,5],'interest':[['A','B'],['A','C','B'],['B','D'],['A','C'],['A','B','D']],
                        'location':['Z','Y','Z','Y','Z']})

#new code: location dictionary
loc_dict = users_df.set_index('userid')['location'].to_dict()

#new code: function that removes userid combinations when locations are different
def restrict_users(all_combs):
    return [comb for comb in all_combs if loc_dict[comb[0]] == loc_dict[comb[1]]]

dictionary = users_df.set_index('userid')['interest'].map(set).to_dict()

#new function applied below
out = pd.DataFrame(restrict_users(list(itertools.combinations(users_df.userid, 2))), columns=['userid', 'relative_id']) 
out['common_interest'] = [list(dictionary[x] & dictionary[y]) for x, y in out.values]
#location column added to the dataframe
out['location'] = out['userid'].map(loc_dict)

out

【讨论】:

    【解决方案2】:

    这是我的解决方案,无需创建子数据框。不过看起来有点重。致谢 @AlexK 以获取框架的初始化。

    import pandas as pd
    import itertools
    
    df = pd.DataFrame({'userid':[1,2,3,4,5],'interest':[['A','B'],['A','C','B'],['B','D'],['A','C'],['A','B','D']],
                            'location':['Z','Y','Z','Y','Z']})
    # Builds a dictionary of location as key and a list of index of users in df as value
    idxlocation = df.groupby('location').apply(lambda x: x.index.values).to_dict()
    
    new_frame = []
    for k, v  in idxlocation.items():
        for i in itertools.combinations(v, 2):
            userid = df.loc[i[0], 'userid']
            relativeid = df.loc[i[1], 'userid']
            new_frame.append((userid, relativeid, [j for j in set(df.loc[i[0], 'interest']).intersection(set(df.loc[i[1], 'interest']))], k))
    
    out = pd.DataFrame(new_frame)
    out.columns = ['userid', 'relative_id', 'common_interest', 'location']
    
    >>>out
       userid  relative_id common_interest location
    0       2            4          [A, C]        Y
    1       1            3             [B]        Z
    2       1            5          [A, B]        Z
    3       3            5          [D, B]        Z
    

    【讨论】:

      猜你喜欢
      • 2021-10-24
      • 1970-01-01
      • 1970-01-01
      • 2021-12-29
      • 1970-01-01
      • 1970-01-01
      • 2018-01-10
      • 1970-01-01
      • 2020-08-06
      相关资源
      最近更新 更多