如何将含键值格式字符串的data.frame转换为结构化数据
解决方案
针对你遇到的键值对拆分、处理不一致性的需求,这里用tidyverse系列包给出完整处理方案,完美匹配你的期望输出:
library(tidyverse) # 原始数据 dat <- data.frame(title = c("How To", "Why To", "When To"), id = c("001", "005", "102"), tags = c("Type: Article, Topics: solo, Length: 3.5, Topics: self help, DIY", "case study, thinking, English, Type: Paper, Topics: philosophy", "Language: EN, Type: Checklist, Topics: scheduling, time-management")) # 步骤1:清理tags中的无分类前缀(非键值对的开头内容) dat_clean <- dat %>% mutate(tags_clean = str_remove(tags, "^[^:]+(?=\\s*[A-Za-z]+:)")) %>% mutate(tags_clean = str_trim(str_remove(tags_clean, "^,\\s*"))) # 步骤2:拆分键值对、合并重复键的值、转成宽表 result <- dat_clean %>% separate_rows(tags_clean, sep = ",\\s*") %>% filter(str_detect(tags_clean, ":")) %>% separate(tags_clean, into = c("key", "value"), sep = ":\\s*", extra = "merge") %>% group_by(id, key) %>% summarise(value = str_c(value, collapse = ", "), .groups = "drop") %>% pivot_wider(names_from = key, values_from = value) %>% left_join(dat, ., by = "id") %>% select(title, id, tags, Language, Type, Length, Topics) # 查看结果 print(result)
分步解释
清理无分类前缀:
用正则^[^:]+(?=\\s*[A-Za-z]+:)精准匹配开头所有非键值对的内容(直到第一个带冒号的键出现),直接移除;再清理掉开头残留的逗号和空格,确保后续拆分的准确性。拆分与处理重复键:
separate_rows把每个tags条目拆成单独的键值对行,方便处理重复的键(比如第一条数据里的两个Topics);- 过滤掉没有冒号的无效条目,避免干扰;
separate拆分键和值,extra = "merge"参数保证值中的空格(比如self help)不会被错误拆分;- 按
id和key分组,把同一键的多个值合并成一个字符串,用逗号分隔; pivot_wider转成宽表格式,自动给缺失的键填充NA;- 最后和原始数据合并,调整列顺序匹配你的期望输出。
输出结果
title id tags Language Type Length Topics 1 How To 001 Type: Article, Topics: solo, Length: 3.5, Topics: self help, DIY NA Article 3.5 solo, self help, DIY 2 Why To 005 case study, thinking, English, Type: Paper, Topics: philosophy NA Paper NA philosophy 3 When To 102 Language: EN, Type: Checklist, Topics: scheduling, time-management EN Checklist NA scheduling, time-management
内容的提问来源于stack exchange,提问作者daRknight
相关产品推荐
相关产品推荐

