【问题标题】:Similarity of two rows placed into new column, based on column condition基于列条件将两行放入新列的相似性
【发布时间】:2020-08-27 00:57:23
【问题描述】:

当且仅当另一列满足特定标准时,我正在努力将一系列两行之间的相似性转化为一系列新列。例如,假设我有一个 df,其中有四个人、他们的朋友状态和他们的社交偏好。

preference = {'person': ["Sara","Jordan","Amish","Kimmie"],'game_night':[30,10,50,30], 'movies': [10,10,20,10], 'dinner_out': [20,20,30,10] }
near = {'person': ["Sara","Jordan","Amish","Kimmie"], 'friendSara':[0,1,0,0], 'friendJordan': [1,0,1,1], 'friendAmish': [0,1,0,1], 'friendKimmie': [0,1,1,0]}

df = pd.DataFrame(data=preference)
near_df = pd.DataFrame(data=near)

如果您觉得有更好的方法来组织 df 或解决问题,请挑战我,但我希望在此示例中创建一系列名为“simSara”、“simJordan”的新列,等等,在每个人的 3 个社交偏好和其他社交偏好之间填充 dot(person1_preferences, person2_preferences)/(norm(person1_preferences)*norm(person2_preferences))。例如,添加名为“simSara”的第一列将在第二行填充 0.873(因为 Jordan 和 Sara 是朋友)

【问题讨论】:

    标签: python calculated-columns cosine-similarity


    【解决方案1】:

    创建一个 numpy 数组,将每个人的偏好汇总为一个向量,每个向量也是一个 np.array

    prefVec = df.apply(lambda x: np.array([x.game_night,x.movies,x.dinner_out]),axis=1).to_numpy()
    

    应该是这样的:

    array([
        array([30, 10, 20]), 
        array([10, 10, 20]), 
        array([50, 20, 30]),
        array([30, 10, 10])
    ], 
    dtype=object)
    

    为您的操作定义一个自定义函数:

    def getVal(v1,v2):
        return np.sum(v1*v2)/(np.sqrt((v1**2).sum())*np.sqrt((v2**2).sum()))
    

    现在我们基本上需要使用我们之前定义的函数来做一个自定义的内积。 np.frompyfunc 接受我们的自定义函数和指定自定义函数的输入和输出数量的整数。通过将prefVec 垂直和水平传递给这个customFunc,我们广播了这个操作。这意味着我们的水平prefVec 被“拉伸”成一个矩阵,然后我们将让它通过我们的列prefVec 的自定义内积:

    customFunc = np.frompyfunc(getVal,2,1)
    out = customFunc(prefVec.reshape(-1,1),prefVec)
    #                  ^column prefVec       ^horizontal prefVec
    

    out 应该是这样的:

    array([[1.        , 0.87287156, 0.99717646, 0.96698756],
           [0.87287156, 1.        , 0.86094603, 0.73854895],
           [0.99717646, 0.86094603, 1.        , 0.97823198],
           [0.96698756, 0.73854895, 0.97823198, 1.        ]])
    

    通过从原始df.person 列中获取人员列表将其转换为数据框

    pd.DataFrame(
        out,
        columns=df.person.apply(lambda x: 'sim{}'.format(x)).to_numpy(),
        index=df.person
    ).reset_index()
    

    输出:

        person  simSara simJordan   simAmish    simKimmie
    0   Sara    1.000000    0.872872    0.997176    0.966988
    1   Jordan  0.872872    1.000000    0.860946    0.738549
    2   Amish   0.997176    0.860946    1.000000    0.978232
    3   Kimmie  0.966988    0.738549    0.978232    1.000000
    

    如果您希望它们都在同一个数据框中,请将上述输出与person 列上的原始 df 合并

    【讨论】:

    • 谢谢,杰夫,非常感谢。将不得不花一些时间消化。
    • 抱歉编辑了一堆东西,在工作中匆匆忙忙地做了,想起了我以后应该做得更好的东西
    • 更加感动和感激?
    猜你喜欢
    • 2021-06-28
    • 2021-11-07
    • 1970-01-01
    • 2022-11-27
    • 2021-11-16
    • 2022-11-16
    • 1970-01-01
    • 1970-01-01
    • 2017-04-13
    相关资源
    最近更新 更多