R语言处理数据框行内逗号分隔层级排序文本 生成品牌排名列
R语言拆分逗号分隔排名字段生成品牌独立排名列
原始数据
示例输入数据框如下:
df <- data.frame ("user.id" = c("usr1", "usr2", "usr3", "usr4"), "gender" = c("m", "f", "m", "f"), "fav.car.rank" = c("toyota, subaru, honda", "honda, subaru, toyota", "toyota, honda, subaru", "subaru, toyota, honda"))
其中fav.car.rank列存储逗号分隔的汽车品牌排序,从左到右对应喜爱度从高到低,需求是将每个品牌拆分为独立列,列值为该用户对对应品牌的喜爱排名(示例中排名数值越高代表喜爱度越高,与目标输出结构匹配)。
目标输出结构:
| user.id | gender | toyota | subaru | honda |
|---|---|---|---|---|
| usr1 | m | 3 | 2 | 1 |
| usr2 | f | 1 | 2 | 3 |
| usr3 | m | 3 | 1 | 2 |
| usr4 | f | 2 | 3 | 1 |
实现方案
方案1:Base R实现(无需安装加载第三方包)
核心思路是先拆分字符串,再按位置匹配排名,最后合并回原表:
# 按逗号拆分品牌字符串,自动兼容逗号前后的空格 split_brands <- strsplit(df$fav.car.rank, split = ",\\s*") # 提取所有出现过的唯一品牌名作为新列名 all_brands <- unique(trimws(unlist(split_brands))) # 逐行计算每个品牌的排名:位置越靠前(喜爱度越高)分值越高 rank_df <- t(sapply(split_brands, function(brand_seq) { # 3个品牌时,第1位(最喜爱)得3分,第2位得2分,第3位得1分 rank_pair <- setNames(length(brand_seq):1, trimws(brand_seq)) # 按统一品牌顺序返回排名值 rank_pair[all_brands] })) # 合并原表的基础字段和排名字段,得到最终结果 final_df <- cbind(df[, c("user.id", "gender")], as.data.frame(rank_df))
运行后打印final_df即可得到和目标结构完全一致的结果。
方案2:tidyverse实现(管道操作逻辑更直观)
适合日常使用tidyverse生态做数据处理的场景:
library(tidyverse) final_df <- df %>% # 将逗号分隔的品牌拆分为多行 separate_rows(fav.car.rank, sep = ",\\s*") %>% # 按用户分组,为每个品牌计算对应排名 group_by(user.id) %>% mutate( rank = n():1, # 越靠前的品牌分值越高,如需最喜爱为1分改为1:n()即可 fav.car.rank = trimws(fav.car.rank) ) %>% # 将长表转为宽表,品牌作为独立列 pivot_wider(names_from = fav.car.rank, values_from = rank) %>% ungroup()
注意事项
- 上述代码自动兼容不同数量的品牌,后续如果
fav.car.rank中新增品牌,无需修改代码即可自动生成对应新列 - 如果需要调整排名规则(最喜爱为1、最不喜爱为最大序号),只需将代码中
length(brand_seq):1/n():1修改为1:length(brand_seq)/1:n()即可 - 代码中加入了空格处理逻辑,不会因为逗号前后空格数量不一致导致品牌匹配错误
内容的提问来源于stack exchange,提问作者Naim Cinar
相关产品推荐
相关产品推荐

