R语言:基于条件筛选多列并重构数据集的高效实现方法
高效整理R语言数据集:提取电话、地址并合并姓名
原始数据集
id = 1:5 col1 = c("john", "henry", "adam", "jenna", "Phone: 222 2222") col2 = c("river B8C 9L4", "Field U9H 5E2 PP", "NA", "ocean A1B 5H1 dd", "dave") col3 = c("Phone: 111 1111 111", "steve", "forest K0Y 1U9 hu2", "NA", "NA") col4 = c("matt", "peter", "Phone: 333 333 1113", "Phone: 444 111 1153", "kevin") my_data = data.frame(id, col1, col2, col3, col4)
数据集输出:
id col1 col2 col3 col4 1 1 john river B8C 9L4 Phone: 111 1111 111 matt 2 2 henry Field U9H 5E2 PP steve peter 3 3 adam NA forest K0Y 1U9 hu2 Phone: 333 333 1113 4 4 jenna ocean A1B 5H1 dd NA Phone: 444 111 1153 5 5 Phone: 222 2222 dave NA kevin
需求
- 保留
id列作为第一列 - 提取每行中的电话号码(格式为
Phone: xxx xxx...) - 提取包含正则
(([A-Z] ?[0-9]){3})格式的地址数据 - 将剩余非电话、非地址的姓名类数据合并为单独的
name列
期望输出
id name address phone 1 1 john matt river B8C 9L4 Phone: 111 1111 111 2 2 henry steve peter Field U9H 5E2 PP NA 3 3 adam forest K0Y 1U9 hu2 Phone: 333 333 1113 4 4 jenna ocean A1B 5H1 dd Phone: 444 111 1153 5 5 dave kevin NA Phone: 222 2222
已尝试的部分代码
my_data$col1[grep("Phone", my_data$col1)] my_data$col2[grep("Phone", my_data$col2)] my_data$col3[grep("Phone", my_data$col3)] my_data$col4[grep("Phone", my_data$col4)] my_data$col1[grep( '(([A-Z] ?[0-9]){3})|.', '\1' , my_data$col1)] my_data$col2[grep('(([A-Z] ?[0-9]){3})|.', '\1', my_data$col2)] my_data$col3[grep('(([A-Z] ?[0-9]){3})|.', '\1', my_data$col3)] my_data$col4[grep('(([A-Z] ?[0-9]){3})|.', '\1', my_data$col4)]
高效解决方案
使用tidyverse工具包按行处理,一次性完成分类提取与合并:
library(tidyverse) # 定义三类数据的判断函数 is_phone <- function(x) str_detect(x, "^Phone: ") is_address <- function(x) str_detect(x, "(([A-Z] ?[0-9]){3})") & !is_phone(x) & x != "NA" is_name <- function(x) !is_phone(x) & !is_address(x) & x != "NA" # 按行处理并生成结果 result <- my_data %>% rowwise() %>% mutate( # 提取每行的电话号码,无则为NA phone = first(c_across(col1:col4)[is_phone(c_across(col1:col4))], default = NA), # 提取每行的地址,无则为NA address = first(c_across(col1:col4)[is_address(c_across(col1:col4))], default = NA), # 合并所有姓名类数据为一个字符串 name = str_c(c_across(col1:col4)[is_name(c_across(col1:col4))], collapse = " ") ) %>% # 保留目标列 select(id, name, address, phone) %>% # 处理空姓名为NA mutate(name = ifelse(name == "", NA, name)) # 查看结果 print(result)
代码说明
rowwise():将数据按行分组,确保后续操作逐行执行c_across(col1:col4):获取当前行的所有目标列数据- 自定义判断函数:精准区分电话、地址、姓名三类数据
first(..., default = NA):提取每行中符合条件的第一个值,无匹配则返回NAstr_c(..., collapse = " "):将同一行的所有姓名用空格连接成字符串
内容的提问来源于stack exchange,提问作者stats_noob
相关产品推荐
相关产品推荐

