我正在尝试使用前两个前缀修复邮政编码输入错误。作为一个可重复的例子,(假设(假设邮政编码以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功能(
我们可以使用stringr
中的str_sub
来获取前2个字符,并将其与%in%
一起使用
library(dplyr)
library(stringr)
df %>%
mutate(state = replace(state, str_sub(zip, 1, 2) %in% ma_zip,
'MA'))
或者另一个选项是regex
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
也许:
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
以下是一些基本的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
另一个选项是使用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