You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

代码说明

  1. rowwise():将数据按行分组,确保后续操作逐行执行
  2. c_across(col1:col4):获取当前行的所有目标列数据
  3. 自定义判断函数:精准区分电话、地址、姓名三类数据
  4. first(..., default = NA):提取每行中符合条件的第一个值,无匹配则返回NA
  5. str_c(..., collapse = " "):将同一行的所有姓名用空格连接成字符串

内容的提问来源于stack exchange,提问作者stats_noob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 03:31:04