2015-04-20 5 views
7

Ho il seguente data.frame(incollatura) colonne

Tipo Start End Strand Accesion1 Accesion2 
1 gene 197 1558  +  <NA> SP_0001 
2 CDS 197 1558  + NP_344554  <NA> 
3 gene 1717 2853  +  <NA> SP_0002 
4 CDS 1717 2853  + NP_344555  <NA> 
5 gene 2864 3112  +  <NA> SP_0003 
6 CDS 2864 3112  + NP_344556  <NA> 

ci sono valori più "Tipo", come tRNA, regione, esone o rRNA, ma sono solo interessati a combinare questi due , gene e CDS

e vorrei ottenere le seguenti

Start End Accesion1 Accesion2 
1 197 1558 NP_344554 SP_0001 

ma solo quando i valori di inizio e fine del gene e CDS coincidono. Ho cercato di utilizzare selezionare, organizzare e mutare con dplyr, ma è un po 'complicato per me, per sbarazzarsi di AN

+1

Potrebbe essere necessario fornire un po 'più particolari, sul fatto che 'gene/CDS' verifica in coppie o no. Non è chiaro perché hai menzionato che ci sono altri valori 'tRNA, region, exon' ecc Supponiamo, se' df1 $ Start [6] <- 2964' quale sarebbe il risultato atteso per il set di dati di esempio – akrun

+0

Sì, vengono in coppia La soluzione che hai dato sembra funzionare molto bene. Dato che alcuni tipi extra sono presenti, alcuni NA compaiono, ma posso facilmente scartarli con cassette complete Stavo cercando una soluzione con dplyr, solo perché mi piace. Ma la soluzione (hai cancellato?) funziona bene –

+1

Puoi verificare se questo funziona 'library (data.table); setDT (df1) [, id: = cumsum (Tipo == 'gene')] [, lista (Accesion1 = na.omit (Accesion1), Accesion2 = na.omit (Accesion2)), list (id, Start, End)] ' – akrun

risposta

4

Una versione dplyr con summarize_each:

DF %>% 
    group_by(Start, End) %>% 
    summarise_each(funs(max), Accesion1, Accesion2) 

Produce:

Source: local data frame [3 x 4] 
Groups: Start 

    Start End Accesion1 Accesion2 
1 197 1558 NP_344554 SP_0001 
2 1717 2853 NP_344555 SP_0002 
3 2864 3112 NP_344556 SP_0003 

Considerando una AccessionX varibles sono carattere (non funziona con il fattore), così come la condizione che Le coppie Start End contengono solo due valori, uno ciascuno di Tipo e Gene, come nel tuo set di dati.

+0

Non so perché, ma non capisco. un sapply (df, classe) mi dice che Accesion1 e 3 sono character. Ma ottengo questo Inizio Fine Accesion1 Accesion2 1 197 1558 NA NA 2 1717 2853 NA NA 3 2864 3112 NA NA 4 3196 4311 NA NA 5 4382 4951 NA NA 6 4952 8461 NA NA 7 8519 8785 NA NA 8 8778 9146 NA NA 9 9151 9273 NA NA 10 9266 10534 NA NA –

+1

penso 'summarise_each (funs (max = max (., na.rm = TRUE)), Accesion1, Accesion2)' possono essere necessari – akrun

+0

Sì, akrun, tutto a posto –

3

Ecco una soluzione che utilizza aggregate():

df <- data.frame(Tipo=c('gene','CDS','gene','CDS','gene','CDS'), Start=c(197,197,1717,1717,2864,2864), End=c(1558,1558,2853,2853,3112,3112), Strand=c('+','+','+','+','+','+'), Accesion1=c(NA,'NP_344554',NA,'NP_344555',NA,'NP_344556'), Accesion2=c('SP_0001',NA,'SP_0002',NA,'SP_0003',NA)); 
df2 <- df[df$Tipo%in%c('gene','CDS'),c('Start','End','Accesion1','Accesion2')]; 
aggregate(df2[,c('Accesion1','Accesion2')], df2[,c('Start','End')], function(x) x[!is.na(x)]); 
## Start End Accesion1 Accesion2 
## 1 197 1558 NP_344554 SP_0001 
## 2 1717 2853 NP_344555 SP_0002 
## 3 2864 3112 NP_344556 SP_0003 

Precomputing df2 è necessaria caso ci sono file non-gene non-CDS nel data.frame originale; per aggregare correttamente solo il gene e le righe CDS, le righe non-gene non-CDS devono essere escluse da entrambi x e by. (Naturalmente, i dati di esempio hanno solo il gene e le righe CDS, quindi non è tecnicamente necessario per i dati di esempio.)

Questa soluzione presuppone che ogni volta che due righe hanno gli stessi valori Start e End, devono essere coppie di geni/CDS (al contrario di gene/gene o CDS/CDS).

+0

Grazie per il commento. Non ho controllato la mia soluzione per tutti i casi in cui l'OP ha menzionato che funziona (in base ai commenti). – akrun

+0

Anche a me piace questa risposta. Grazie –

2

Ecco un modo potenziale. Scegli le file con gene e CDS. Quindi, si raggruppano i dati per Inizio e Fine. Potrebbero esserci gruppi di START/END con 1 o 3+ righe. Quindi, assicurati di scegliere i gruppi START/END con due righe. Inoltre, vuoi assicurarti di avere sia gene che CDS (length(unique(Tipo)) == 2). Infine, si prende non NA elemento Accesion1 e Accesion 2.

filter(df, Tipo %in% c("gene", "CDS")) %>% 
group_by(Start, End) %>% 
filter(n() == 2 & length(unique(Tipo)) == 2) %>% 
summarise(Accesion1 = Accesion1[!is.na(Accesion1)], 
      Accesion2 = Accesion2[!is.na(Accesion2)]) 

Ecco un esempio di pseudo.

mydf <- structure(list(Tipo = structure(c(2L, 1L, 2L, 1L, 2L, 2L), .Label = c("CDS", 
"gene"), class = "factor"), Start = c(197, 197, 1717, 1717, 2864, 
2864), End = c(1558, 1558, 2853, 2853, 3112, 3112), Strand = structure(c(1L, 
1L, 1L, 1L, 1L, 1L), .Label = "+", class = "factor"), Accesion1 = structure(c(NA, 
1L, NA, 2L, NA, 3L), .Label = c("NP_344554", "NP_344555", "NP_344556" 
), class = "factor"), Accesion2 = structure(c(1L, NA, 2L, NA, 
3L, NA), .Label = c("SP_0001", "SP_0002", "SP_0003"), class = "factor")), .Names = c("Tipo", 
"Start", "End", "Strand", "Accesion1", "Accesion2"), row.names = c(NA, 
-6L), class = "data.frame") 


    Tipo Start End Strand Accesion1 Accesion2 
1 gene 197 1558  +  <NA> SP_0001 
2 CDS 197 1558  + NP_344554  <NA> 
3 gene 1717 2853  +  <NA> SP_0002 
4 CDS 1717 2853  + NP_344555  <NA> 
5 gene 2864 3112  +  <NA> SP_0003 
6 gene 2864 3112  + NP_344556  <NA> 


filter(mydf, Tipo %in% c("gene", "CDS")) %>% 
group_by(Start, End) %>% 
filter(n() == 2 & length(unique(Tipo)) == 2) %>% 
summarise(Accesion1 = Accesion1[!is.na(Accesion1)], 
      Accesion2 = Accesion2[!is.na(Accesion2)]) 

# Start End Accesion1 Accesion2 
#1 197 1558 NP_344554 SP_0001 
#2 1717 2853 NP_344555 SP_0002 
+0

@akrun Sono stato un po 'arrugginito. Mi chiedo l'esempio sopra chiarisce il tuo punto. Per favore fatemi sapere se mi manca il vostro punto. – jazzurro

+1

Sì, chiarisce il punto – akrun

+0

Ciò significa che il mio data.frame deve contenere fattori ?. Il mio in realtà non contiene fattori. È un semplice data.frame e il tuo codice non funziona. –

4

Si potrebbe provare

library(data.table) 
setDT(df1)[, id:=cumsum(Tipo == 'gene')][, 
    list(Accesion1=na.omit(Accesion1), Accesion2=na.omit(Accesion2)) , 
           list(id, Start, End)]