2015-02-20 10 views
6

Chciałbym spłaszczyć listy wyodrębnione z tabel HTML. Minimalny przykład działania przedstawiono poniżej. Przykład zależy od pakietu stringr w R. Pierwszy przykład wykazuje pożądane zachowanie.Wyodrębnij ostatnią 4-cyfrową liczbę z serii w R używając stringr

years <- c("2005-", "2003-") 
unlist(str_extract_all(years,"[[:digit:]]{4}")) 

[1] "2005" "2003" 

Poniższy przykład daje niepożądany wynik, gdy próbuję dopasować ostatnią 4-cyfrową liczbę w szeregu innych liczb.

years1 <- c("2005-", "2003-", "1984-1992, 1996-") 
unlist(str_extract_all(years1,"[[:digit:]]{4}$")) 

character(0) 

Jak rozumiem z dokumentacji, należy podać $ na końcu wzorca w celu zażądania meczu na końcu łańcucha. Wolałbym dopasować z drugiego przykładu liczby "2005", "2003" i "1996".

+0

'substr (years1,1,4)' zawiera listę "2005", "2003", "1984", gdzie chciałbym uzyskać "2005", "2003" i "1996" – Daniel

+0

Jak o 'sub ('. * (\\ d {4}). *', '\\ 1', years1)'? – jbaums

+0

@jbaums, który na pewno działa, czy mógłbyś podać zasób/wyjaśnienie swojego rozwiązania? – Daniel

Odpowiedz

7

Pakiet stringi ma wygodnych funkcji, które działają na określonych częściach łańcucha. Możesz znaleźć ostatnie wystąpienie czterech następujących po sobie cyfr.

library(stringi) 

x <- c("2005-", "2003-", "1984-1992, 1996-") 

stri_extract_last_regex(x, "\\d{4}") 
# [1] "2005" "2003" "1996" 

Inne sposoby, aby uzyskać ten sam rezultat są

stri_sub(x, stri_locate_last_regex(x, "\\d{4}")) 
# [1] "2005" "2003" "1996" 

## or, since these count as words 
stri_extract_last_words(x) 
# [1] "2005" "2003" "1996" 

## or if you prefer a matrix result 
stri_match_last_regex(x, "\\d{4}") 
#  [,1] 
# [1,] "2005" 
# [2,] "2003" 
# [3,] "1996" 
+1

Często patrzę na twoje posty, myśląc: Naprawdę muszę się zapoznać z tym pakietem _... :) – jbaums

+1

Dziękuję za dokładną reakcję i ekspozycję na 'stringi' – Daniel

7

Można użyć zasady R sub za to dość łatwo:

sub('.*(\\d{4}).*', '\\1', years1) 

## [1] "2005" "2003" "1996" 

Wzór być dopasowane tutaj jest .* (zero lub więcej dowolnych znaków), po których następują cztery kolejne cyfry, które przechwytujemy przez umieszczenie w nawiasach), po których następuje zero lub więcej znaków.

sub zastępuje dopasowany wzór wartością z drugiego argumentu. W tym przypadku \\1 wskazuje, że chcemy zastąpić cały dopasowany wzór pierwszym przechwyconym podłańcuchem (tj. Czterema kolejnymi cyframi).

W tym przypadku wyrażenie regularne jest chciwe, więc ominie początkowe dopasowania \\d{4}, konsumując je za pomocą .*. Zapisuje się tylko ostatnia sekwencja czterech kolejnych cyfr.

+0

Jest to bardzo przydatne rozwiązanie, natknąłem się w obliczu z podobnym problemem. Jak trudno byłoby zmienić wyrażenie, aby dopasować * pierwsze * cztery cyfry zamiast ostatnich? – Konrad

+1

@Konrad - możesz to zrobić za pomocą 'sub ('\ \ D * (\\ d {4}). *', '\\ 1', years1)', gdzie '\\ D *' oznacza zero lub więcej znaki, które nie mają cyfr. – jbaums

2

Koniec łańcucha $ zakotwiczenie zapewnia pozycję na końcu łańcucha.

Mówiąc, dopasuj dokładnie cztery cyfry na końcu napisu. Niestety, dzieje się tak, że cyfry starają się dopasować, a silnik regex posuwa się naprzód, próbując potwierdzić tę pozycję i nie udaje się, ponieważ nie ma na tej pozycji i kolejno cofa się próbując je dopasować.

Aby to naprawić, możesz zużywać wszystkie znaki aż do ostatniego zestawu cyfr.

years1 <- c('2005-', '2003-', '1984-1992, 1996-') 
unlist(str_extract_all(years1, perl('.*\\K\\d{4}'))) 
# [1] "2005" "2003" "1996" 
Powiązane problemy