在R中使用自定义方法构建归一化Levenshtein及语义距离矩阵
自定义距离矩阵生成方案
前置准备
首先加载所需依赖包:
library(tidyverse) library(vwr)
1. 归一化Levenshtein字符串距离矩阵
计算逻辑说明
匹配你给出的示例规则,相同字符串距离为1,其余值为1减去编辑距离除以较长字符串长度的结果。
实现代码
假设你的原始数据框为raw_df,字符串存储在word列:
# 提取所有唯一字符串 unique_words <- unique(raw_df$word) # 生成所有两两字符串组合的长表 string_dist_long <- crossing(word1 = unique_words, word2 = unique_words) %>% mutate( # 计算两个字符串的最大长度 longer_len = pmax(str_length(word1), str_length(word2)), # 调用vwr包计算编辑距离 edit_dist = map2_dbl(word1, word2, ~ levenshtein.distance(.x, .y)), # 按规则归一化,匹配示例对角为1的要求 normed_dist = 1 - (edit_dist / longer_len) ) # 长表转矩阵 string_dist_matrix <- string_dist_long %>% pivot_wider(names_from = word2, values_from = normed_dist) %>% column_to_rownames("word1") %>% as.matrix()
2. 二维语义距离矩阵
计算逻辑说明
形状、图案两个特征每不同一项加1,相同语义距离为0,和你的规则完全匹配。
实现代码
假设你的原始数据框中,形状存储在shape列,图案存储在pattern列:
# 提取所有唯一语义组合,生成语义名称 unique_meaning <- raw_df %>% distinct(shape, pattern) %>% mutate(meaning_name = str_c("带", pattern, shape)) # 生成所有两两语义组合的长表 meaning_dist_long <- crossing( meaning1 = unique_meaning, meaning2 = unique_meaning ) %>% unpack(c(meaning1, meaning2), names_sep = "_") %>% mutate( meaning_dist = (meaning1_shape != meaning2_shape) + (meaning1_pattern != meaning2_pattern) ) %>% # 保留需要的列用于转矩阵 select(meaning1_name, meaning2_name, meaning_dist) # 长表转矩阵 meaning_dist_matrix <- meaning_dist_long %>% pivot_wider(names_from = meaning2_name, values_from = meaning_dist) %>% column_to_rownames("meaning1_name") %>% as.matrix()
3. 已有长表直接转矩阵方法
如果你已经提前计算完所有两两对的距离长表(固定三列:行标识、列标识、距离值),可以用以下方法快速转换:
# 假设长表为dist_long,三列名为row_item、col_item、distance # 方法1:tidyverse风格 dist_matrix <- dist_long %>% pivot_wider(names_from = col_item, values_from = distance) %>% column_to_rownames("row_item") %>% as.matrix() # 方法2:base R快速实现 dist_matrix <- as.matrix(xtabs(distance ~ row_item + col_item, data = dist_long))
内容的提问来源于stack exchange,提问作者shleen
相关产品推荐
相关产品推荐

