R语言中循环索引j被忽略,多组数据未处理问题排查
问题原因分析
你的代码核心问题是双层循环的结果存储逻辑错误,导致除最后一次迭代的分组外,其他分组的数据全部被覆盖丢失:
- 外层循环遍历分组
j,内层循环遍历方法i时,每次都将results[[i]]赋值为当前j分组的i方法结果。这意味着当你处理下一个分组时,会直接覆盖之前所有方法对应的结果,最终results列表里只保留了最后一个分组的所有方法数据。 - 最后用
do.call(cbind.data.frame, results)做列合并,会把同一个分组的多方法结果强行拼在一起,完全丢失其他分组的信息,最终只能看到最后一个分组的数据(你看到的A分组,说明在你的环境中最后一次j循环处理的是A)。
修复后的代码
以下代码调整了结果存储逻辑,先按分组生成完整的方法结果数据框,再通过行合并保留所有分组的数据:
library(stringdist) library(tidyverse) set.seed(123) # 生成数据集 myFun <- function(n = 5000) { a <- do.call(paste0, replicate(5, sample(LETTERS, n, TRUE), FALSE)) paste0(a, sprintf("%04d", sample(9999, n, TRUE)), sample(LETTERS, n, TRUE)) } col1 = myFun(100) col2 = myFun(100) col3 = myFun(100) col4 = myFun(100) group <- c("A","B","C","D") group = sample(group, 100, replace=TRUE) example = data.frame(col1, col2, col3, col4, group) # 定义距离方法 method = c("osa", "lv", "dl", "hamming", "lcs", "qgram", "cosine", "jaccard", "jw","soundex") results = list() # 提前获取所有唯一分组,避免循环内重复计算 g = unique(example$group) l = length(g) for (j in 1:l) { # 提取当前分组数据 current_group = g[j] group_data = example[example$group == current_group, ] # 初始化当前分组的结果数据框 group_result = data.frame() for (i in 1:length(method)) { current_method = method[i] col1_col2_name = paste0("col1_col2_", current_method) col3_col4_name = paste0("col3_col4_", current_method) # 计算两两字符串距离并整理格式 col1_col2_dist = stringdistmatrix(group_data$col1, group_data$col2, method = current_method, useNames = "string") %>% as_tibble(rownames = "a") %>% pivot_longer(-1, names_to = "b", values_to = col1_col2_name) %>% select(all_of(col1_col2_name)) col3_col4_dist = stringdistmatrix(group_data$col3, group_data$col4, method = current_method, useNames = "string") %>% as_tibble(rownames = "a") %>% pivot_longer(-1, names_to = "b", values_to = col3_col4_name) %>% select(all_of(col3_col4_name)) # 合并当前方法的结果到分组数据框 if (i == 1) { group_result = cbind(col1_col2_dist, col3_col4_dist) } else { group_result = cbind(group_result, col1_col2_dist, col3_col4_dist) } } # 添加分组标识列 group_result$group = current_group # 将当前分组结果加入列表 results[[j]] = group_result } # 行合并所有分组的结果 final = do.call(rbind.data.frame, results) # 验证分组分布 table(final$group)
额外说明
- 结果行数说明:上述代码保留了
stringdistmatrix的两两比较逻辑,因此每个分组的结果行数是该分组样本数的平方(例如A分组21个样本,结果行数为21×21=441),这和你之前看到的441条A分组数据对应。 - 单样本距离需求:如果你只需要每个样本自身
col1-col2和col3-col4的距离(而非两两比较),可以把stringdistmatrix替换为stringdist,这样结果行数和原分组样本数一致:col1_col2_dist = stringdist(group_data$col1, group_data$col2, method = current_method) %>% as.data.frame() %>% setNames(col1_col2_name) col3_col4_dist = stringdist(group_data$col3, group_data$col4, method = current_method) %>% as.data.frame() %>% setNames(col3_col4_name)
内容的提问来源于stack exchange,提问作者stats_noob
相关产品推荐
相关产品推荐

