获取行之间的 jaccard 距离,而无需在 python 中的列上预先进行一种热编码
Get jaccard distance between rows without preformong one hot encoding on the column in python
我有一个 table 看起来像这样:
id feature_1 feature_2 feature_3
1 A x r
23 A v r
56 B z r
我想以一种有效的方式在行 (id) 之间创建某种 Jaccard 距离,而不是将特征转换为一个热编码列(很多可能性)。
如何得到行间相似度总和的结果?类似的东西:
id_1 id_2 similarity num_of_features distance
1 23 2 3 2/3
1 56 1 3 1/3
23 56 1 3 1/3
我的代码:
def create_pairs(ids_list):
pairs_list = []
for (p1,p2) in itertools.combinations(ids_list,2):
pair = [p1,p2]
pairs_list.append(pair)
return pairs_list
def get_distance(id_1, id_2, df):
????
return distance
ids_list= list(df['id'].unique())
pairs_list = create_pairs(ids_list=ids_list)
pairs_df = pd.DataFrame(pairs_list,columns=['id_1','id_2'])
distance_list = []
for [id_1, id_2] in pairs_list:
distance = get_distance(id_1=id_1, id_2=id_2,df=df)
pairs_df['distance'] = distance_list
我相信 scikit 中没有 row-wise 内置的 jaccard 距离功能,但您可以尝试以下操作:
from sklearn.metrics import jaccard_score
import pandas as pd
data = [['a', 'x', 'r'], ['a', 'v', 'r'], ['b', 'z', 'r']]
# Create the pandas DataFrame
df = pd.DataFrame(data, columns = ['feature_1', 'feature_2', 'feature_3'])
print(df)
df_cmp = df.copy()
for index, row in df.iterrows():
for index_, row_ in df_cmp.iterrows():
if index == index_:
continue
print(index, index_, jaccard_score(row,row_, average='weighted'))
df_cmp = df_cmp.drop(index) #remove after as done already
创建一个您将使用的副本 - 这样您就可以删除已经传递的行。然后您可以计算行的 jaccard 距离。输出:
feature_1 feature_2 feature_3
0 a x r
1 a v r
2 b z r
行分数:
0 1 0.6666666666666666
0 2 0.3333333333333333
1 2 0.3333333333333333
您可以不用打印,而是将其写入数据框,稍后再使用。然而这种方法有复杂性O(n*log(n))
,也许会有更快的方法。
编辑:
不知何故我没有注意到你已经创建了对,因此只需将你的问号替换为:
distance = jaccard_score(df.iloc[id_1],df.iloc[id_2], average='weighted')
试试这个,应该会更快:
def get_distance(id_1, id_2, df):
similarity_count = df.loc[id_1]==df.loc[id_2]
similarity_count = similarity_count.sum(0)
distance = 1-(similarity_count /len(list(df.columns)))
return distance
我有一个 table 看起来像这样:
id feature_1 feature_2 feature_3
1 A x r
23 A v r
56 B z r
我想以一种有效的方式在行 (id) 之间创建某种 Jaccard 距离,而不是将特征转换为一个热编码列(很多可能性)。
如何得到行间相似度总和的结果?类似的东西:
id_1 id_2 similarity num_of_features distance
1 23 2 3 2/3
1 56 1 3 1/3
23 56 1 3 1/3
我的代码:
def create_pairs(ids_list):
pairs_list = []
for (p1,p2) in itertools.combinations(ids_list,2):
pair = [p1,p2]
pairs_list.append(pair)
return pairs_list
def get_distance(id_1, id_2, df):
????
return distance
ids_list= list(df['id'].unique())
pairs_list = create_pairs(ids_list=ids_list)
pairs_df = pd.DataFrame(pairs_list,columns=['id_1','id_2'])
distance_list = []
for [id_1, id_2] in pairs_list:
distance = get_distance(id_1=id_1, id_2=id_2,df=df)
pairs_df['distance'] = distance_list
我相信 scikit 中没有 row-wise 内置的 jaccard 距离功能,但您可以尝试以下操作:
from sklearn.metrics import jaccard_score
import pandas as pd
data = [['a', 'x', 'r'], ['a', 'v', 'r'], ['b', 'z', 'r']]
# Create the pandas DataFrame
df = pd.DataFrame(data, columns = ['feature_1', 'feature_2', 'feature_3'])
print(df)
df_cmp = df.copy()
for index, row in df.iterrows():
for index_, row_ in df_cmp.iterrows():
if index == index_:
continue
print(index, index_, jaccard_score(row,row_, average='weighted'))
df_cmp = df_cmp.drop(index) #remove after as done already
创建一个您将使用的副本 - 这样您就可以删除已经传递的行。然后您可以计算行的 jaccard 距离。输出:
feature_1 feature_2 feature_3 0 a x r 1 a v r 2 b z r
行分数:
0 1 0.6666666666666666 0 2 0.3333333333333333 1 2 0.3333333333333333
您可以不用打印,而是将其写入数据框,稍后再使用。然而这种方法有复杂性O(n*log(n))
,也许会有更快的方法。
编辑:
不知何故我没有注意到你已经创建了对,因此只需将你的问号替换为:
distance = jaccard_score(df.iloc[id_1],df.iloc[id_2], average='weighted')
试试这个,应该会更快:
def get_distance(id_1, id_2, df):
similarity_count = df.loc[id_1]==df.loc[id_2]
similarity_count = similarity_count.sum(0)
distance = 1-(similarity_count /len(list(df.columns)))
return distance