2013-02-05 17 views
5

Mam listę stacji meteorologicznych i ich lokalizacji według szerokości i długości geograficznej. Wystąpił problem z formatowaniem, a niektóre z nich mają godziny i minuty, a inne godziny, minuty i sekundy. Mogę znaleźć wzór za pomocą regex, ale mam problem z wyodrębnianiem poszczególnych elementów.R regex/gsub: wypakuj część wzoru

Oto dane:

> head(wthrStat1) 
    Station  lat  lon 
1940 K01R 31-08N 092-34W 
1941 K01T 28-08N 094-24W 
1942 K03Y 48-47N 096-57W 
1943 K04V 38-05-50N 106-10-07W 
1944 K05F 31-25-16N 097-47-49W 
1945 K06D 48-53-04N 099-37-15W 

Chciałbym coś takiego:

Station  latHr latMin latSec latDir lonHr lonMin lonSec lonDir 
    1940 K01R 31 08  00  N  092 34  00  W 
    1941 K01T 28 08  00  N  094 24  00  W 
    1942 K03Y 48 47  00  N  096 57  00  W 
    1943 K04V 38 05  50  N  106 10  07  W 
    1944 K05F 31 25  16  N  097 47  49  W 
    1945 K06D 48 53  04  N  099 37  15  W 

mogę dostać mecze do tej regex:

data.format <- "\\d{1,3}-\\d{1,3}(?:-\\d{1,3})?[NSWE]{1}" 
grep(data.format, wthrStat1$lat) 

ale jestem pewien, w jaki sposób uzyskać poszczególne części w kolumny. Wypróbowałem kilka rzeczy takich jak:

wthrStat1$latHr <- ifelse(grepl(data.format, wthrStat1$lat), gsub(????), NA) 

ale bez powodzenia.

Oto dput():

> dput(wthrStat1[1:10,]) 
structure(list(Station = c("K01R", "K01T", "K03Y", "K04V", "K05F", 
"K06D", "K07G", "K07S", "K08D", "K0B9"), lat = c("31-08N", "28-08N", 
"48-47N", "38-05-50N", "31-25-16N", "48-53-04N", "42-34-28N", 
"47-58-27N", "48-18-03N", "43-20N"), lon = c("092-34W", "094-24W", 
"096-57W", "106-10-07W", "097-47-49W", "099-37-15W", "084-48-41W", 
"117-25-42W", "102-24-23W", "070-24W")), .Names = c("Station", 
"lat", "lon"), row.names = 1940:1949, class = "data.frame") 

Wszelkie sugestie?

+0

Czy próbowałeś * grupowania * każdej kolumny za pomocą pharentesis w regex? –

+0

@OscarMederos: Nie, jak byś to zrobił? – screechOwl

+0

Nie wiem, jak działa wyrażenie regularne w 'R', ale w większości języków można tworzyć grupy, włączając to, co jest potrzebne w pharentesis. Jak 'id = (\ d +)'. Jeśli twój mecz to "id = 1234", pierwszą grupą będzie "1234". –

Odpowiedz

6

jest bardzo nieefektywne, mam nadzieję, że ktoś inny miał lepsze rozwiązanie:

dat <- read.table(text =' Station  lat  lon 
1940 K01R 31-08N 092-34W 
1941 K01T 28-08N 094-24W 
1942 K03Y 48-47N 096-57W 
1943 K04V 38-05-50N 106-10-07W 
1944 K05F 31-25-16N 097-47-49W 
1945 K06D 48-53-04N 099-37-15W', head=T) 


pattern <- '([0-9]+)[-]([0-9]+)([-|A-Z]+)([0-9]*)([A-Z]*)' 

dat$latHr <- gsub(pattern,'\\1',dat$lat) 
dat$latMin <- gsub(pattern,'\\2',dat$lat) 

latSec <- gsub(pattern,'\\4',dat$lat) 
latSec[nchar(latSec)==0] <- '00' 
dat$latSec <- latSec 

latDir <- gsub(pattern,'\\5',dat$lat) 
latDir[nchar(latDir)==0] <- latDir[nchar(latDir)!=0][1] 
dat$latDir <- latDir 

dat 
    Station  lat  lon latHr latMin latSec latDir 
1940 K01R 31-08N 092-34W 31  08  00  N 
1941 K01T 28-08N 094-24W 28  08  00  N 
1942 K03Y 48-47N 096-57W 48  47  00  N 
1943 K04V 38-05-50N 106-10-07W 38  05  50  N 
1944 K05F 31-25-16N 097-47-49W 31  25  16  N 
1945 K06D 48-53-04N 099-37-15W 48  53  04  N 
7

strapplyc w pakiecie gsubfn będzie wyodrębnić każdą grupę w wyrażeniu regularnym otoczony nawiasami:

library(gsubfn) 
data.format <- "(\\d{1,3})-(\\d{1,3})-?(\\d{1,3})?([NSWE]{1})" 
parts <- strapplyc(wthrStat1$lat, data.format, simplify = rbind) 
parts[parts == ""] <- "00" 

co daje :

> parts 
     [,1] [,2] [,3] [,4] 
[1,] "31" "08" "00" "N" 
[2,] "28" "08" "00" "N" 
[3,] "48" "47" "00" "N" 
[4,] "38" "05" "50" "N" 
[5,] "31" "25" "16" "N" 
[6,] "48" "53" "04" "N" 
[7,] "42" "34" "28" "N" 
[8,] "47" "58" "27" "N" 
[9,] "48" "18" "03" "N" 
[10,] "43" "20" "00" "N" 
+0

Dzięki za wskazanie pakietu gsubfn. Podoba mi się sposób, w jaki pasuje do R przez rozszerzenie funkcji * apply. BTW, dla mnie, strapplyc zwraca dane.frame z 1 kolumną z 6 rzędami, które zawierają "c". strapply, podczas gdy części <- strapply (df $ lat, pattern, FUN = c, simplify up = rbind) działają zgodnie z oczekiwaniami. (wersja 0.6-5 gsubfn na R 2.15.1, nie znalazła tcltk). – cbare

+1

@cbare, to błąd. Jest teraz naprawiony w repozytorium subversion. Aby go użyć: 'library (gsbufn); source ("http://gsubfn.googlecode.com/svn/trunk/R/strapplyc.R") ". W odpowiedziach na najczęstsze pytania znajduje się również informacja o instalacji tcltk: https://code.google.com/p/gsubfn/#FAQs –

2

Kolejna odpowiedź, używając stringr:

# example data 
data <- 
"Station  lat  lon 
1940 K01R 31-08N 092-34W 
1941 K01T 28-08N 094-24W 
1942 K03Y 48-47N 096-57W 
1943 K04V 38-05-50N 106-10-07W 
1944 K05F 31-25-16N 097-47-49W 
1945 K06D 48-53-04N 099-37-15W" 

## read string into a data.frame 
df <- read.table(text=data, head=T, stringsAsFactors=F) 

pattern <- "(\\d{1,3})-(\\d{1,3})(?:-(\\d{1,3}))?([NSWE]{1})" 

library(stringr) 
str_match(df$lat, pattern) 

To daje data.frame z jednej kolumny dla całego łańcucha pasującego oraz dodatkową kolumnę dla każdego capture-grupy.

 [,1]  [,2] [,3] [,4] [,5] 
[1,] "31-08N" "31" "08" "" "N" 
[2,] "28-08N" "28" "08" "" "N" 
[3,] "48-47N" "48" "47" "" "N" 
[4,] "38-05-50N" "38" "05" "-50" "N" 
[5,] "31-25-16N" "31" "25" "-16" "N" 
[6,] "48-53-04N" "48" "53" "-04" "N" 

string processing zdolność R za postępuje wiele w ciągu ostatnich kilku lat.