R查找以一组数字字符开头的行

问题描述 投票:0回答:4

我正在尝试使用前两个前缀修复邮政编码输入错误。作为可重现的示例,(假设)假设邮政编码以01、02、03和04开头为MA,但我的数据包含以下错误。

ma_zip <- c("01", "02", "03", "04")

df <- data.frame(zip = c("01100", "02223", "04332", "03234"),
                 state = c("MA", "NJ", "NY", "NY")) %>%
  mutate(zip = as.character(zip),
         state = as.character(state))

我尝试通过以下两种方式修复错误。在第一种(也是蛮力的)方法中,我一步一步地修复了问题,并得到了想要的结果。

df_cleaned1 <- df %>%
  mutate(state = replace(state, startsWith(zip, "02"), "MA"),
         state = replace(state, startsWith(zip, "03"), "MA"),
         state = replace(state, startsWith(zip, "04"), "MA"))

> df_cleaned1
    zip state
1 01100    MA
2 02223    MA
3 04332    MA
4 03234    MA

但这不是最有趣的事情,因为我必须反复复制和粘贴。因此,我尝试了以下操作,但这似乎不起作用(也没有引发错误消息)。

df_cleaned2 <- df %>%
  mutate(state = replace(state, startsWith(zip, paste(ma_zip, collapse="|")), "MA"))

> df_cleaned2
    zip state
1 01100    MA
2 02223    NJ
3 04332    NY
4 03234    NY

是否有一种有效的方式来生成df_cleaned1,同时又避免了暴力破解? (不必使用startWith函数)

r
4个回答
2
投票

也许:

library(dplyr)

df %>% mutate(state = replace(state, substr(zip, 1, 2) %in% ma_zip, 'MA'))

输出:

    zip state
1 01100    MA
2 02223    MA
3 04332    MA
4 03234    MA

2
投票

我们可以使用str_sub中的stringr来获取前2个字符,并将其与%in%一起使用

library(dplyr)
library(stringr)
df %>%
     mutate(state = replace(state, str_sub(zip, 1, 2) %in% ma_zip,
              'MA'))

或者另一个选择是正则表达式

df %>%
    mutate(state = replace(state, str_detect(zip, str_c("^(", str_c(ma_zip, collapse="|"), ")")), 'MA'))
#   zip state
#1 01100    MA
#2 02223    MA
#3 04332    MA
#4 03234    MA

0
投票

这里有一些基本的R解决方案

df <- within(df, state <- replace(state,gsub("(\\w{2}).*","\\1",zip) %in% ma_zip,"MA"))

df <- within(df, state <- replace(state,substr(zip,1,2) %in% ma_zip,"MA"))

诸如此类

> df
    zip state
1 01100    MA
2 02223    MA
3 04332    MA
4 03234    MA

0
投票

另一种选择是使用grepl而不是startsWith。您将需要创建以下模式^01|^02|^03|^04,可以使用粘贴功能对方法(@ qnp1521)进行一些修改来完成:

df_cleaned2 <- df %>% mutate(state = replace(state, grepl(paste("^",ma_zip, collapse ="|",sep=""),zip), "MA"))

df_cleaned2
1 01100    MA
2 02223    MA
3 04332    MA
4 03234    MA
© www.soinside.com 2019 - 2024. All rights reserved.