2016-01-15 19 views
7

Sto cercando di suddividere un vettore stringa in più variabili utilizzando le espressioni regolari in R, preferibilmente in un modo dplyr-tidyr usando il comando tidyr :: extract. Per insctance nel vettore sotto:Interrompi la stringa in più colonne usando tidyr :: extract regex

sasdic <- data.frame(a=c(
    '@1 ANO_CENSO 5. /*Ano do Censo*/', 
    '@71 TP_SEXO $Char1. /*Sexo*/', 
    '@72 TP_COR_RACA $Char1. /*Cor/raça*/', 
    '@74 FK_COD_PAIS_ORIGEM 4. /*Código País de origem*/')) 

vorrei per il:

  • primo numero ([0-9] +) per andare a "int_pos" variabili
  • il nome della variabile in contatto sottolineando ([a-zA-Z _] +) per passare alla variabile "var_name"
  • Il secondo numero o il termine $ Char1 (potrebbe essere $ Char2, ecc.) per passare a var "x". Ho pensato ([0-9] + | $ Char [0-9] +) potrebbe selezionare questo?
  • Infine, qualunque cosa si trovi tra "/ * ... /" per andare alla variabile "etichetta" (non si conosce la regex per questo). Tutte le altre lettere accentate intermidiate (spazi vuoti, " " "/","" dovrebbe essere disconsidered)

Questo sarebbe il risultato

d <- data.frame(int_pos=c(1,72,72,74), 
       var_name=c('ANO_CENSO','TP_SEXO','TP_COR_RACA','FK_COD_PAIS_ORIGEM'), 
       x=c('5','Chart1','$Char1','4'), 
       label=c('Ano do Censo','Sexo','Cor/raça','Código País de origem')) 

Ho provato a costruire un'espressione regolare per Questo. Questo è quello che ho ottenuto finora:

sasdic %>% extract(a, c('int_pos','var_name','x','label'), 
        "([0-9]+)([a-zA-Z_]+)([0-9]+|$Char[0-9]+)(something to get the label") 
      -> d 

sopra l'espressione regolare è incompleta. Inoltre, non so come rendere esplicito nella sintassi del comando extract, quali sono le parti da recuperare e quali sono le parti da tralasciare.

risposta

6

Nella regex utilizzato, ci sono matchng uno più personaggi più punteggiatura ([[:punct:]]+) IT @ seguiti da catturare la parte numerica ((\\d+) - questa sarà la nostra prima colonna di interesse), seguito da uno o più spazi bianchi (\\s+), seguito dal secondo gruppo di cattura (\\S+ - uno o più caratteri non di spazio bianco, ad esempio "ANO_CENSO" per la prima riga), seguito dallo spazio (\\s+), quindi acquisiamo il terzo gruppo (([[:alum:]$]+), ad esempio uno o più caratteri che includono l'alfanumerico insieme a $ in modo che corrisponda a $Char1), successivamente corrispondiamo a uno o più caratteri che non sono una lettera ([^A-Za-z]+ - questo dovrebbe sbarazzarsi dello spazio e *) e l'ultima parte catturiamo uno o più caratteri che non sono * (([^*]+).

sasdic %>% 
     extract(a, into=c('int_pos', 'var_name', 'x', 'label'), 
    "[[:punct:]](\\d+)\\s+(\\S+)\\s+([[:alnum:]$]+)[^A-Za-z]+([^*]+)") 

# int_pos   var_name  x     label 
#1  1   ANO_CENSO  5   Ano do Censo 
#2  71   TP_SEXO $Char1     Sexo 
#3  72  TP_COR_RACA $Char1    Cor/raça 
#4  74 FK_COD_PAIS_ORIGEM  4 Código País de origem 
7

Questa è un'altra opzione, anche se utilizza il pacchetto data.table anziché tidyr:

library(data.table) 
setDT(sasdic) 

# split label 
sasdic[, c("V1","label") := tstrsplit(a, "/\\*|\\*/")]     
# remove leading "@", split remaining parts 
sasdic[, c("int_pos","var_name","x") := tstrsplit(gsub("^@","",V1)," +")] 
# remove unneeded columns 
sasdic[, c("a","V1") := NULL]            

sasdic 

#     label int_pos   var_name  x 
# 1:   Ano do Censo  1   ANO_CENSO  5. 
# 2:     Sexo  71   TP_SEXO $Char1. 
# 3:    Cor/raça  72  TP_COR_RACA $Char1. 
# 4: Código País de origem  74 FK_COD_PAIS_ORIGEM  4. 

Ciò presuppone che le "parti restanti" (a parte l'etichetta) sono separati da spazi.


Questo potrebbe anche essere fatto in un blocco (che è quello che vorrei fare):

sasdic[, c("a","label","int_pos","var_name","x") := { 
    x = tstrsplit(a, "/\\*|\\*/") 
    x1s = tstrsplit(gsub("^@","",x[[1]])," +") 
    c(list(NULL), x1s, x[2]) 
}]