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

R语言数据框处理:拆分State列保留州名、提取年份至新列

问题描述

数据框的State列混合存储了三类信息:州名、HB/HF法案编号、法律生效日期。需要实现两个需求:

  • 处理后State列仅保留州名
  • 新增一列存储对应法律的生效年份

现有预处理代码如下:

Mintz = read.csv('https://github.com/bandcar/mintz/raw/main/State%20Legislation%20on%20Biosimilars2.csv')
mintz = Mintz

# 删除第二列为空值的行
mintz = mintz[mintz$Substitution.Requirements != "", ]

# 删除第一列值为"State"的冗余表头行
mintz=mintz[mintz$State != "State", ]

# 重置行号
mintz= mintz %>% data.frame(row.names = 1:nrow(.)) 

# 删除第34行的波多黎各(PR,非美国州级单位)
mintz = mintz[-34,]

# 重置行号
mintz= mintz %>% data.frame(row.names = 1:nrow(.)) 

最初判断可以用strsplit()搭配gsub()实现需求,但因为State列内容没有固定分隔符,不清楚具体编写逻辑。


问题补充

目前仍未实现State列仅保留州名的需求。
关于年份提取,找到了一段可运行代码,但不理解其生效逻辑,且存在异常:

mintz2 = mintz
mintz2$Year = sub('.*(\\d{4}).*', '\\1', mintz2$State)

疑问点:

  • 之前认知里\d是匹配字面字符,.匹配单个字符,无法理解\1的含义
  • 第20行明尼苏达州的数据没有对应年份时,代码提取到了非数字字符,和\d仅匹配数字的认知冲突

解答

正则代码原理解释

你对正则语法的认知存在几个偏差,先逐点说明:

  • 正则中\d不是匹配字面字符"d",而是匹配0-9的任意单个数字,在R的字符串语法中需要写双反斜杠\\d才能表示正则转义的\d
  • 正则中.匹配任意单个字符,.*表示匹配任意长度(包含0长度)的任意字符
  • 小括号()在正则中表示捕获组,会把括号内匹配到的内容临时存储,替换字符串里的\\1就是引用第一个捕获组存储的匹配内容

你找到的这行代码逻辑是:匹配「任意前缀 + 连续4位数字 + 任意后缀」的整段字符串,把整段内容替换为捕获组抓到的4位连续数字,也就是年份。
明尼苏达行出现非数字结果的原因很简单:如果字符串里找不到符合规则的匹配项,sub()不会执行替换,会直接返回原始字符串,自然就会出现非数字的结果。

修复年份提取逻辑

要解决无匹配时返回原字符串的问题,加一层匹配判断即可,找不到4位连续数字时返回NA:

# 方法1:用stringr包的str_extract,无匹配默认返回NA,代码更简洁
library(stringr)
mintz$Year = as.integer(str_extract(mintz$State, "\\d{4}"))

# 方法2:基础R实现,不需要额外装包
mintz$Year = ifelse(
  grepl("\\d{4}", mintz$State),
  as.integer(sub('.*(\\d{4}).*', '\\1', mintz$State)),
  NA_integer_
)

提取纯净州名

观察State列的内容规律:所有州名都是纯英文字母(包含空格),后续的法案编号、生效日期都是从第一个数字,或者HB/HF/SB这类法案前缀开头的。只要把第一个数字/法案前缀及其之后的所有内容清空,再去掉首尾多余空格即可:

# 匹配第一个出现的数字、HB/HF/SB标识,将该位置及之后的所有内容替换为空
mintz$State = trimws(sub("(\\d|HB|HF|SB).*", "", mintz$State))

运行后逐行检查即可确认,所有州名都被正确提取,没有残留法案编号或日期内容。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 12:06:20