将 Dataframe 字符串列解析为街道、城市、州和邮政编码

Parse Dataframe string column into Street, City, State & Zip code

我正在尝试将以下固定字符串分成几列,如街道、城市、州和邮政编码。是否可以通过 INSTR & Subtr 方法在 SQLDF 中执行此操作?

示例地址字符串。困难的部分是 NV 和邮政编码解析。

727 Wright Brothers Ln, Las Vegas, NV 89119, USA 

我能够使用 sqldf/instr 解析 city/street 信息,但无法解析 state/zip 代码

的最后两个值
parsed_tweetAddressdf <- sqldf("SELECT lon, lat, result, substr(result,0,instr(result,',')) AS street, substr(result,instr(result,',')+1,instr(result,',')-1) AS city from tweetAddressdf")

这里有一些备选方案。他们都按照问题的要求使用 instrsubstr,尽管第三个也写出数据并将其读回(除了使用 instrsubstr)。最后的注释指出,在普通 R 中或在 gsubfn.

中使用 read.pattern 也很容易做到这一点

1) 假设 state, zip 和 country 字段的宽度是固定的 只有一个样本记录不可能知道你的一般情况是什么但是如果我们假设每条记录结束在 SS ZZZZZ, USA 中,SS 是两个字母的州缩写,ZZZZZ 是 5 位数字的邮政编码,那么这有效:

DF <- data.frame(v = "727 Wright Brothers Ln, Las Vegas, NV 89119, USA")

library(sqldf)
sqldf("select 
  substr(v, 0, instr(v, ',')) street,
  substr(v, instr(v, ',') + 2, length(v) - 16 - instr(v, ',')) city,
  substr(v, -13, 2) state,
  substr(v, -10, 5) zip
 from DF")

给予:

                  street      city state   zip
1 727 Wright Brothers Ln Las Vegas    NV 89119

2) 严格基于逗号分隔(state/zip除外) 这种方法以额外的复杂性为代价避免了 (1) 中的某些假设。它采用前两个逗号分隔的字段、2 个字符的状态以及之后的所有内容到下一个逗号作为 zip。

它使用三重嵌套 select。最里面的 select 表示 a 将输入字符串解析为:streeta.rest。下一个向外进行表示b returns street 已经从a 解析,并将a.rest 解析为cityb.rest.最外层的 returns streetcity 已经解析加上它 returns b.rest 中的两个状态字符以及 b.rest 中超出它们的所有内容下一个逗号为 zip.

library(sqldf)

sqldf("
  select
    street,
    city,
    substr(b.rest, 1, 2) state,
    substr(b.rest, 4, instr(b.rest, ',') - 4) zip
  from (
    select 
      street, 
      substr(a.rest, 0, instr(a.rest, ',')) city,
      substr(a.rest, instr(a.rest, ',') + 2) rest 
    from (select 
            substr(v, 0, instr(v, ',')) street,
            substr(v, instr(v, ',') + 2) rest
    from DF) a) b
")

给予:

                  street      city state   zip
1 727 Wright Brothers Ln Las Vegas    NV 89119

3) read.csv.sql 如果可以把它写出来再读回来,那么我们可以使用 read.csv.sql,一个围绕 [=41 的包装器=].虽然题目没问,但是这个也解析出国:

write.table(DF, "addresses.csv", row.names = FALSE, col.names = FALSE, 
            sep = ",", quote = FALSE)

read.csv.sql("addresses.csv", header = FALSE, sql = 
       "select V1 street, 
               V2 city, 
               substr(V3, 2, 2) state, 
               substr(V3, 4) zip, 
               V4 country 
        from file")

给予:

                  street       city state    zip country
1 727 Wright Brothers Ln  Las Vegas    NV  89119     USA

注 1:这在普通 R 中也很容易。

dd <- read.table(text = as.character(DF$v), sep = ",",
 col.names = c("street", "city", "state_zip", "country"))

transform(dd, 
              state = substring(state_zip, 2, 3), 
              zip = substring(state_zip, 4))[c(1, 2, 5, 6, 4)]

给予:

                  street       city state    zip country
1 727 Wright Brothers Ln  Las Vegas    NV  89119     USA

注 2: 使用 gsubfn 中的 read.pattern 更容易:

library(gsubfn)

pat <- "(.*), (.*), (..) (.*), (.*)"
read.pattern(text = as.character(DF$v), pattern = pat, 
   col.names = c("street", "city", "state", "zip", "country"))

给予:

                  street      city state   zip country
1 727 Wright Brothers Ln Las Vegas    NV 89119     USA