如何用R语言(dplyr/stringr)自动生成按权重排序的物品序列?
解决方案
你的代码存在几个关键问题:
- 数据集创建语法错误,items与ID长度不匹配;
- 使用
str_count匹配字符串会错误统计包含目标数字的其他数值(比如str_count("18", "1")会返回1,导致percentB计算错误); - 手动创建百分比列繁琐且易出错,无法灵活处理排序和序列组装需求;
- 逻辑混淆了"重复物品不增加权重"的定义(实际应为按物品出现次数占总次数的比例计算权重,而非唯一物品均分)。
以下是符合需求的完整解决方案:
修正步骤与代码
library(dplyr) library(tidyr) library(stringr) # 修正数据集,确保ID与items长度匹配 df <- data.frame( ID = seq(1:6), items = c( "1,1,8,16,8,18,18,1,16,2,8,5,1", "2,1,2,1,6", "18,18,19,18,4", "1,19,2", "2,2,2,4,2,6,1", "6,2,2" ), stringsAsFactors = FALSE ) # 定义数字到物品的映射表,便于统一转换 item_map <- tibble( num = c("1", "2", "3", "4", "5", "6", "18", "19"), item = c("B", "M", "O", "Ac", "C", "T", "Pp", "Pt") ) # 核心处理流程 df_final <- df %>% group_by(ID) %>% # 将逗号分隔的items拆分为单独行 separate_rows(items, sep = ",") %>% # 统计每个数字的出现次数 count(items, name = "count") %>% # 计算该行总元素数与各物品的占比百分比 mutate( total = sum(count), percent = (count / total) * 100 ) %>% # 将数字映射为对应的物品名称 left_join(item_map, by = c("items" = "num")) %>% # 按规则排序:百分比降序,百分比相同时按物品字母升序 arrange(desc(percent), item) %>% # 按出现次数重复物品名称(对应占比比例) mutate(item_repeat = strrep(item, count)) %>% # 合并所有重复的物品为最终输出序列 summarise(final_output = str_c(item_repeat, collapse = "")) %>% # 合并回原数据集 right_join(df, by = "ID") %>% select(ID, items, final_output) # 查看结果 print(df_final)
代码说明
- 数据集修正:调整ID与items的长度匹配,避免后续分组错误;
- 映射表定义:统一管理数字与物品的对应关系,避免手动硬编码;
- 拆分与计数:用
separate_rows拆分items,彻底解决字符串匹配的计数错误问题; - 排序逻辑:严格按照「百分比降序→物品字母升序」的规则排序;
- 序列组装:用
strrep按物品出现次数重复名称,合并后得到符合需求的输出序列(例如占比50%的物品会重复2次,25%的物品各重复1次)。
内容的提问来源于stack exchange,提问作者opl
相关产品推荐
相关产品推荐

