2014-11-27 1 views
4

У меня есть фрейм данных, как показано ниже. Это набор выборки данные с равномерными ищут модели, но все данными не очень неравномерны:извлечение разделенных запятыми строк

locationid  address  
1073744023 525 East 68th Street, New York, NY  10065, USA 
1073744022 270 Park Avenue, New York, NY 10017, USA  
1073744025 Rockefeller Center, 50 Rockefeller Plaza, New York, NY 10020, USA 
1073744024 1251 Avenue of the Americas, New York, NY 10020, USA 
1073744021 1301 Avenue of the Americas, New York, NY 10019, USA 
1073744026 44 West 45th Street, New York, NY 10036, USA 

Мне нужно найти название города и страны с этого адреса. Я попытался следующие:

1) strsplit Это дает мне список, но я не могу получить доступ к последним или третий последний элемент из этого.

2) Регулярные выражения найти страну легко

str_sub(str_extract(address, "\\d{5},\\s.*"),8,11) 

, но для города

str_sub(str_extract(address, ",\\s.+,\\s.+\\d{5}"),3,comma_pos) 

Я не могу найти comma_pos как это снова приводит меня к одной и той же проблемы. Я считаю, что есть более эффективный способ решить эту проблему, используя любой из вышеперечисленных.

ответ

3

Split данные

ss <- strsplit(data,",")` 

Тогда

n <- sapply(s,len) 

даст количество элементов (так что вы можете работать в обратном направлении). Затем

mapply(ss,"[[",n) 

дает вам последний элемент. Или вы можете сделать

sapply(ss,tail,1) 

чтобы получить последний элемент.

Чтобы получить второй до последнего (или в более общем случае) вам нужно

sapply(ss,function(x) tail(x,2)[1]) 
+1

sapply (ss, tail, 1) работает, но sapply (ss, tail, 2) дает мне ошибку: Ошибка: неправильный размер результата (12), ожидаемый 6 или 1 – Cagg

+0

Спасибо. Это потрясающе, и обновление действительно решило проблему !!! – Cagg

2

Я думаю, вы хотите что-то подобное.

> x <- "1073744026 44 West 45th Street, New York, NY 10036, USA" 
> regmatches(x, gregexpr('^[^,]+, *\\K[^,]+', x, perl=T))[[1]] 
[1] "New York" 
> regmatches(x, gregexpr('^[^,]+, *[^,]+, *[^,]+, *\\K[^\n,]+', x, perl=T))[[1]] 
[1] "USA" 

Regex объяснение:

  • ^ Утверждает, что мы находимся в самом начале.
  • [^,]+ Соответствует любому персонажу, но не , один или несколько раз. Измените его на [^,]*, если ваш фреймворк содержит пустые поля.
  • , Соответствует буквальным ,
  • <space>* соответствует нулю или более пробелов.
  • \K отбрасывает ранее сопоставленные символы из печати. В качестве вывода будут отображаться символы, соответствующие шаблону, следующему \K.
+0

привет. Я новичок в регулярном выражении. не могли бы вы объяснить, что это значит? – Cagg

0

Как насчет этой модели:

,\s(?<city>[^,]+?),\s(?<shortCity>[^,]+?)(?i:\d{5},)(?<country>\s.*) 

Эта модель соответствует этому три группы:

  1. "group": "city", "value": "New York"
  2. "group": "shortCi ти», "значение": "Нью-Йорк"
  3. "группа": "страна", "значение": "США"
4

Попробуйте этот код:

library(gsubfn) 

cn <- c("Id", "Address", "City", "State", "Zip", "Country") 

pat <- "(\\d+) (.+), (.+), (..) (\\d+), (.+)" 
read.pattern(text = Lines, pattern = pat, col.names = cn, as.is = TRUE) 

дает следующие данные. кадр из которого его легко отодрать компоненты:

  Id         Address  City State Zip Country 
1 1073744023      525 East 68th Street New York NY 10065  USA 
2 1073744022       270 Park Avenue New York NY 10017  USA 
3 1073744025 Rockefeller Center, 50 Rockefeller Plaza New York NY 10020  USA 
4 1073744024    1251 Avenue of the Americas New York NY 10020  USA 
5 1073744021    1301 Avenue of the Americas New York NY 10019  USA 
6 1073744026      44 West 45th Street New York NY 10036  USA 

Объяснение Он использует эту модель (если в кавычки, обратные косые черты должны быть в два раза):

(\d+) (.+), (.+), (..) (\d+), (.+) 

визуализировали с помощью следующей debuggex железнодорожной диаграмме - более увидеть это Debuggex Demo:

Regular expression visualization

и объяснено в словах следующим образом:

  • "(\\d+)" - один или более цифр (представляющий Id), а затем
  • " " пространства с последующим
  • "(.+)" - любая не пустая строка (представляющее Address) с последующим
  • ", " - запятая и пробел с последующим
  • "(.+)" - любая не пустая строка (представляющая City), а затем от
  • ", " - запятой и пробелом с последующим
  • "(..)" - два символа (представляющих State) с последующим
  • " " - пространство с последующим
  • "(\\d+)" - одна или более цифр (представляющих Zip) с последующим
  • ", " - запятой и пробел, затем
  • "(.+)" - любой непустой строки (представляющую Country)

Он работает, поскольку регулярные выражения жадные, всегда пытаясь найти самую длинную строку, которая может соответствовать возврату назад, когда последующие части регулярного выражения не совпадают.

Преимущество этого appraoch является то, что регулярное выражение является довольно простым и прямым, и весь код достаточно кратким один read.pattern заявление делает все это:

Примечание: Мы использовали это для Lines:

Lines <- "1073744023 525 East 68th Street, New York, NY 10065, USA 
1073744022 270 Park Avenue, New York, NY 10017, USA 
1073744025 Rockefeller Center, 50 Rockefeller Plaza, New York, NY 10020, USA 
1073744024 1251 Avenue of the Americas, New York, NY 10020, USA 
1073744021 1301 Avenue of the Americas, New York, NY 10019, USA 
1073744026 44 West 45th Street, New York, NY 10036, USA" 
+0

Мне нравится эта демонстрация лучше. –

+2

Их довольно много. Я перечислил те, которые я нашел на домашней странице gsubfn у основания. http://gsubfn.googlecode.com –

3

Вот такой подход, который использует пакет tidyr. Лично я бы просто разделил все на все элементы, используя только tidyr package extract. Это использует регулярное выражение, но по-другому, чем вы просили.

library(tidyr) 

extract(x, address, c("address", "city", "state", "zip", "state"), 
    "([^,]+),\\s([^,]+),\\s+([A-Z]+)\\s+(\\d+),\\s+([A-Z]+)") 

## locationid      address  city state zip state 
## 1 1073744023   525 East 68th Street New York NY 10065 USA 
## 2 1073744022    270 Park Avenue New York NY 10017 USA 
## 3 1073744025   50 Rockefeller Plaza New York NY 10020 USA 
## 4 1073744024 1251 Avenue of the Americas New York NY 10020 USA 
## 5 1073744021 1301 Avenue of the Americas New York NY 10019 USA 
## 6 1073744026   44 West 45th Street New York NY 10036 USA 

Her'es визуальное объяснение регулярного выражения, взятого из http://www.regexper.com/:

enter image description here

0

Использование rex построить регулярное выражение может сделать этот тип задачи немного проще.

x <- data.frame(
    locationid = c(
    1073744023, 
    1073744022, 
    1073744025, 
    1073744024, 
    1073744021, 
    1073744026 
    ), 
    address = c(
    '525 East 68th Street, New York, NY  10065, USA', 
    '270 Park Avenue, New York, NY 10017, USA', 
    'Rockefeller Center, 50 Rockefeller Plaza, New York, NY 10020, USA', 
    '1251 Avenue of the Americas, New York, NY 10020, USA', 
    '1301 Avenue of the Americas, New York, NY 10019, USA', 
    '44 West 45th Street, New York, NY 10036, USA' 
    )) 

library(rex) 

sep <- rex(",", spaces) 

re <- 
    rex(
    capture(name = "address", 
     except_some_of(",") 
    ), 
    sep, 
    capture(name = "city", 
     except_some_of(",") 
    ), 
    sep, 
    capture(name = "state", 
     uppers 
    ), 
    spaces, 
    capture(name = "zip", 
     some_of(digit, "-") 
    ), 
    sep, 
    capture(name = "country", 
     something 
    )) 

re_matches(x$address, re) 
#>      address  city state zip country 
#>1  525 East 68th Street New York NY 10065  USA 
#>2    270 Park Avenue New York NY 10017  USA 
#>3  50 Rockefeller Plaza New York NY 10020  USA 
#>4 1251 Avenue of the Americas New York NY 10020  USA 
#>5 1301 Avenue of the Americas New York NY 10019  USA 
#>6   44 West 45th Street New York NY 10036  USA 

Это регулярное выражение также будет обрабатывать 9-значные почтовые индексы (12345-1234) и другие страны, кроме США.