Python 根据列条件,放入新列的两行的相似性
当且仅当另一列满足特定条件时,我正在努力将一系列两行之间的相似性转化为一系列新的列。例如,假设我有一个有四个人的df,他们的朋友身份和他们的社会偏好Python 根据列条件,放入新列的两行的相似性,python,calculated-columns,cosine-similarity,Python,Calculated Columns,Cosine Similarity,当且仅当另一列满足特定条件时,我正在努力将一系列两行之间的相似性转化为一系列新的列。例如,假设我有一个有四个人的df,他们的朋友身份和他们的社会偏好 preference = {'person': ["Sara","Jordan","Amish","Kimmie"],'game_night':[30,10,50,30], 'movies': [10,10,20,10], 'dinner_out': [20,20,30
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”的新列,这些列将填充
点(person1\u首选项,person2\u首选项)/(norm(person1\u首选项)*norm(person2\u首选项))
在每个人的3个社会偏好和其他偏好之间。例如,添加名为“simSara”的第一列的第二行将填充0.873(因为Jordan和Sara是朋友)创建一个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)
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. ]])
为您的操作定义自定义函数:
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([
array([30, 10, 20]),
array([10, 10, 20]),
array([50, 20, 30]),
array([30, 10, 10])
],
dtype=object)
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合并谢谢,杰夫,非常感谢。我将不得不花一些时间来消化。很抱歉这么多的编辑,在工作中匆匆忙忙地做了这件事,并且记住了我以后应该做得更好的东西。这让我印象深刻,也让我更加感激
pd.DataFrame(
out,
columns=df.person.apply(lambda x: 'sim{}'.format(x)).to_numpy(),
index=df.person
).reset_index()