2015-05-26 17 views
5

Ho un dataframe (TBB) come segueTrova espressione regolare in una colonna e aggiungere una nuova colonna nella stessa dataframe

X.CHROM POS  INFO 

chr1  134324 SAMPLE=LNGHJ; 
chr2  2333  SAMPLE=dd;GERP;.; 
chr2  3334  SAMPLE=;GERP;DDS;CDC=dd; 

vorrei estrarre tutto tra ogni punto e virgola e metterlo nella propria colonna in modo che il risultato sarebbe simile

X.CHROM POS  INFO      
chr1  134324  SAMPLE=LNGHJ;   SAMPLE=LNGHJ  
chr2  2333   SAMPLE=dd;GERP;DDS=3; SAMPLE=dd  GERP DDS=3 
chr2  3334  SAMPLE=;GERP;DDS;  SAMPLE=   GERP DDS 

ho provato questo

TBB3 <- TBB[grep("SAMPLE.*?;", TBB$INFO), ] 
TBB4<-cbind(TBB3,TBB) 

ma le colonne sono dalla parte del torto dimensioni relative tra loro e ovviamente dovrei ripetere questo per ogni parola dopo un punto e virgola quindi non molto efficiente.

risposta

6

Si potrebbe provare stringi::stri_split_fixed

library(stringi) 
cbind(TBB, stri_split_fixed(TBB$INFO, ";", simplify = TRUE, omit_empty = TRUE)) 
# X.CHROM POS     INFO   1 2  3 
# 1 chr1 134324   SAMPLE=LNGHJ; SAMPLE=LNGHJ   
# 2 chr2 2333 SAMPLE=dd;GERP;DDS=3; SAMPLE=dd GERP DDS=3 
# 3 chr2 3334  SAMPLE=;GERP;DDS;  SAMPLE= GERP DDS 
+0

e Autore discussione - avevo bisogno di soluzione simile durante il fine settimana (ma metterla in attesa a causa di vacanze) , quindi grazie! Tuttavia, nel post originale ci sono 4 "elementi" tra i punti e virgola in fila con '3334', mentre le altre righe ne hanno 3. Ciò interromperà la generalità? –

+1

@AlexeyFerapontov non frenerà, ma creerà una voce separata per '.' se questo è ciò che intendi. Anche se questo potrebbe essere trattato anche con una regex corretta, immagino. –

+2

Ottimo! Grazie! –

2

Si potrebbe anche provare il buon vecchio plyr::rbind.fill o dplyr::rbind_list in combinazione con strsplit:

cbind(TBB, 
     do.call(dplyr::rbind_list, 
       lapply(strsplit(as.character(TBB$INFO), split = ";", fixed = TRUE), 
        function(x) 
         as.data.frame(t(x), stringsAsFactors = F)) 
      ) 
) 
# X.CHROM POS      INFO   V1 V2 V3  V4 
# 1 chr1 134324   SAMPLE=LNGHJ; SAMPLE=LNGHJ <NA> <NA> <NA> 
# 2 chr2 2333  SAMPLE=dd;GERP;.; SAMPLE=dd GERP . <NA> 
# 3 chr2 3334 SAMPLE=;GERP;DDS;CDC=dd;  SAMPLE= GERP DDS CDC=dd 
2

Oppure si può utilizzare cSplit da splitstackshape

library(splitstackshape) 
cSplit(TBB, 'INFO', ';', drop=FALSE) 
1

Si potrebbe provare il pacchetto base dalla libreria R:

dd <- read.table(header = TRUE, text = "X.CHROM POS  INFO 
chr1  134324 SAMPLE=LNGHJ; 
chr2  2333  SAMPLE=dd;GERP;.; 
chr2  3334  SAMPLE=;GERP;DDS;CDC=dd;") 


(dd1 <- read.table(text = as.character(dd$INFO), sep = ';', fill = NA, 
        na.strings = c('', '.','NA'))) 

#    V1 V2 V3  V4 V5 
# 1 SAMPLE=LNGHJ <NA> <NA> <NA> NA 
# 2 SAMPLE=dd GERP <NA> <NA> NA 
# 3  SAMPLE= GERP DDS CDC=dd NA 

cbind(dd, dd1[, -ncol(dd1)]) 

#  X.CHROM POS      INFO   V1 V2 V3  V4 
# 1 chr1 134324   SAMPLE=LNGHJ; SAMPLE=LNGHJ <NA> <NA> <NA> 
# 2 chr2 2333  SAMPLE=dd;GERP;.; SAMPLE=dd GERP <NA> <NA> 
# 3 chr2 3334 SAMPLE=;GERP;DDS;CDC=dd;  SAMPLE= GERP DDS CDC=dd 
+0

Continuo a dimenticare la semplice opzione di base R – akrun

0

Utilizzando data.table v1.9.5+:

require(data.table) 
setDT(dat)[, paste0("INFO", 1:4) := tstrsplit(INFO, ";", fixed=TRUE)] 
Problemi correlati