【问题标题】:Convert long state names embedded with other text to two-letter state abbreviations将嵌入其他文本的长状态名称转换为两个字母的状态缩写
【发布时间】:2020-08-10 18:14:35
【问题描述】:

我的目标是识别写在具有其他文本的字符向量中的美国各州,并将各州转换为缩写形式。例如,“北卡罗来纳”到“NC”。如果向量只有长格式的状态名称,这很简单。但是,我的向量在随机位置有其他文本,例如“状态”示例。

states <- c("Plano New Jersey", "NC", "xyz", "Alabama 02138", "Texas", "Town Iowa 99999")

从另一篇文章中我发现了这个:

state.abb[match(states, state.name)]

但它只转换独立的德州

> state.abb[match(states, state.name)]
[1] NA   NA   NA   NA   "TX"

而不是新泽西州、阿拉巴马州和爱荷华州的字符串。

来自Fast grep with a vectored pattern or match, to return list of all matches 我试过了:

sapply(states, grep(pattern = state.name, x = states, value = TRUE))

但是

Error in get(as.character(FUN), mode = "function", envir = envir) : 
  object 'Alabama 02138' of mode 'function' was not found
In addition: Warning message:
In grep(pattern = state.name, x = states, value = TRUE) :
  argument 'pattern' has length > 1 and only the first element will be used

这也不起作用:

sapply(states, function(x) state.abb[grep(state.name, states)])

这个问题没有帮助: regular expression to convert state names to abbreviations

如何将嵌入的长名称转换为州缩写?

编辑:我想返回向量,唯一的变化是州的长名称已被缩写,例如,“Plano New Jersey”变为“Plano NJ”。

感谢您纠正和/或教育我。

【问题讨论】:

  • 您可能会从中得到“纽约,纽约”,此外还有称为“加利福尼亚”的城镇以及州。但是,这对你来说是挑剔的。
  • @Jonathan Leffler:是的,称为州的城镇是一种职业危害。另外,我的城市不止一个州。叹。为什么数据表现不佳?
  • 有一个叫做“真实世界”™的东西,你应该在某个时候访问它(“亲爱的水壶 - 你是黑人!签名,锅”)。它有一个讨厌的习惯,与我们这些编写程序的人设计的整洁方案背道而驰。
  • 最好在网上搜索“城市,州”名称的表格并将其读入 R 进行匹配。
  • @RichardScriven:好点。我在维基百科上找到了 394 个这样的城市,ST 匹配,创建了一个数据框,也可以使用它。例如,我仍在努力分配哥伦布,因为在几个州都有同名的城市。

标签: r regex


【解决方案1】:

这是另一种方法:

library(qdap)
mgsub(state.name, state.abb, states)

## [1] "Plano NJ"      "NC"            "xyz"           "AL 02138"      
## "TX"            "Town IA 99999"

如果您不确定州是否会大写,您可能需要使用:

mgsub(state.name, state.abb, states, ignore.case=TRUE, fixed=FALSE)

【讨论】:

    【解决方案2】:

    试试:

    indx <- paste0(".*(", paste(state.name, collapse="|"), ").*")
    v1 <- gsub(indx, "\\1", states)
    ifelse( v1 %in% state.abb, v1, state.abb[match(v1, state.name)])
    #[1] "NJ" "NC" NA   "AL" "TX" "IA"
    

    如果您只想用缩写而不是其他文本替换状态,您也可以这样做:

    indx1 <- paste(state.name, collapse="|")   
    indx2 <- state.abb[match(v1, state.name)]
    
    mapply(gsub, indx1, indx2, states, USE.NAMES=F)
    #[1] "Plano NJ"      "NC"            "xyz"           "AL 02138"     
    #[5] "TX"            "Town IA 99999"
    

    【讨论】:

    • 我注意到这会将每个匹配状态替换为 alfabet 中首先出现的状态的缩写。例如,输入 "Texas Alabama" 将导致 "AL AL"。有没有办法避免这种情况?
    • @EricBouwers 在 OP 提供的示例中,情况并非如此。所以,我没有那样检查它
    【解决方案3】:

    从问题中不清楚预期结果是什么,但在这里我们假设您希望保留输入中的文本,只需用缩写替换完整的状态名称。

    创建一个列表st,其名称是完整的州名,其值是缩写。然后使用 paste(..., collapse = "|") 创建一个匹配任何状态的正则表达式,并使用 gsubfn 包中的 gsubfn 执行替换。

    library(gsubfn)
    st <- as.list(setNames(state.abb, state.name))
    gsubfn(paste(state.name, collapse = "|"), st, states)
    

    给予:

    [1] "Plano NJ"      "NC"            "xyz"           "AL 02138"     
    [5] "TX"            "Town IA 99999"
    

    【讨论】:

      【解决方案4】:

      如果您不想使用额外的包,您可以使用mapply 函数为所有state.namestate.abb 对应用gsub,例如:

      mapply(gsub,state.name,state.abb,"ALABAMA 123",ignore.case=TRUE,USE.NAMES=FALSE)
      

      这样的结果是一个可以包含替换的列表,例如:

       [1] "AL 123"      "ALABAMA 123" "ALABAMA 123" "ALABAMA 123" "ALABAMA 123" 
       [6] ...
      

      通过从此列表中获取最短的文本,您可以获得所需的结果。因此我们sort the list based on the length of the text 并取第一个元素。

      完整代码:

      replaceState <- function(x) {  
           v = mapply(gsub,state.name,state.abb,x,ignore.case=TRUE, USE.NAMES=FALSE)
           v[order(nchar(v))][1] 
      }
      
      sapply(states, replaceState, USE.NAMES=FALSE)
      

      不幸的是,这种方法只替换了单个状态的名称(最长的)。要替换多个不同的状态,我们需要迭代,例如:

      replaceState <- function(x) {  
           v = mapply(gsub,state.name,state.abb,x,ignore.case=TRUE, USE.NAMES=FALSE)
           v[order(nchar(v))][1] 
      }
      
      replaceStates <- function(x) {
           newX = replaceState(x)
      
           # if they are different a state has been replaced, 
           # we try again to replace all states.
           if(newX != x){ 
                replaceStates(newX)
           } else {
                newX
           }
      }
      
      # Note the 'replaceStates'
      sapply(states, replaceStates, USE.NAMES=FALSE)
      

      【讨论】:

        【解决方案5】:

        试试:

        for(r in 1:nrow(states.list)) {
            states = gsub(states.list[r,1], states.list[r,2], states)
        }
        
        states
        [1] "Plano NJ"      "NC"            "xyz"           "AL 02138"      "TX"            "Town IA 99999"
        

        数据:

        states <- c("Plano New Jersey", "NC", "xyz", "Alabama 02138", "Texas", "Town Iowa 99999")
        
        states.list = structure(list(state.name = structure(c(4L, 1L, 5L, 2L, 3L), .Label = c("Alabama", 
        "Iowa", "Minnesota", "New Jersey", "Texas"), class = "factor"), 
            state.abb = structure(c(4L, 1L, 5L, 2L, 3L), .Label = c("AL", 
            "IA", "MN", "NJ", "TX"), class = "factor")), .Names = c("state.name", 
        "state.abb"), class = "data.frame", row.names = c(NA, -5L))
        
        states.list
          state.name state.abb
        1 New Jersey        NJ
        2    Alabama        AL
        3      Texas        TX
        4       Iowa        IA
        5  Minnesota        MN
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-08-27
          • 2018-10-09
          • 2022-01-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-02-09
          相关资源
          最近更新 更多