2015-04-15 3 views
6

ho un dataframe come segue:includere solo valori anomali da ciascuna colonna in una dataframe

chr leftPos   TBGGT  12_try  324Gtt  AMN2 
    1  24352   34   43   19   43 
    1  53534   2   1   -1   -9 
    2  34   -15   7   -9   -18 
    3  3443   -100  -4   4   -9 
    3  3445   -100  -1   6   -1 
    3  3667   5   -5   9   5 
    3  7882   -8   -9   1   3 

devo creare un ciclo che:

a) Calcola il limite superiore e inferiore (UL e LL) per ogni colonna dalla terza colonna in poi.
b) Include solo le righe che cadono all'esterno di di UL e LL (Zoutliers).
c) Quindi contare il numero di righe in cui Zoutlier è nella stessa direzione (vale a dire positivo o negativo) come il precedente o la riga successiva per lo stesso chr.

L'uscita sarebbe quindi:

ZScore1 TBGGT  12_try  324Gtt  AMN2 
nrow  4   6   4   4 

Finora ho codice come segue:

library(data.table)#v1.9.5 
    f1 <- function(df, ZCol){ 

    #A) Determine the UL and LL and then generate the Zoutliers 
    UL = median(ZCol, na.rm = TRUE) + alpha*IQR(ZCol, na.rm = TRUE) 
    LL = median(ZCol, na.rm = TRUE) - alpha*IQR(ZCol, na.rm = TRUE) 
    Zoutliers <- which(ZCol > UL | ZCol < LL) 

    #B) Exclude Zoutliers per chr if same direction as previous or subsequent row 
    na.omit(as.data.table(df)[, {tmp = sign(eval(as.name(ZCol))) 
    .SD[tmp==shift(tmp) | tmp==shift(tmp, type='lead')]}, 
    by=chr])[, list(.N)]} 

    nm1 <- paste0(names(df) 
    setnames(do.call(cbind,lapply(nm1, function(x) f1(df, x))), nm1)[] 

Il codice è patchato insieme da vari luoghi. Il problema che ho è di combinare le parti A) e B) del codice per ottenere l'output che voglio

+0

Si suppone che 'Zcol' sia essenzialmente' 3: ncol (df) ', cioè tutte le colonne dal numero 3 in poi, o solo una colonna alla volta? –

+0

Dovrebbe calcolarlo una colonna alla volta. Immagino che l'uscita della prima parte del codice dovrebbe darmi tutti i valori anomali di Z con i chr e leftPos in cui credo che faccia. La seconda parte dovrebbe quindi prendere quella colonna e per ogni chr valutare ciascuna riga come descritto. Questa è l'idea. Quindi dovrei passare Zoutliers alla seconda parte? –

+0

Se mi concentro sulla prima parte- come potrei ottenere gli Zoutliers con chr e leftPos associati che potrei quindi passare alla seconda parte del problema –

risposta

0

Puoi provare questa funzione? Non ero sicuro di cosa sia alpha, quindi non sono riuscito a riprodurre l'output previsto e l'ho incluso come variabile nella funzione.

# read your data per copy&paste 
d <- read.table("clipboard",header = T) 
# or as in Frank comment mentioned solution via fread 
d <- data.table::fread("chr leftPos   TBGGT  12_try  324Gtt  AMN2 
            1  24352   34   43   19   43 
            1  53534   2   1   -1   -9 
            2  34   -15   7   -9   -18 
            3  3443   -100  -4   4   -9 
            3  3445   -100  -1   6   -1 
            3  3667   5   -5   9   5 
            3  7882   -8   -9   1   3") 


# set up the function 
foo <- function(x, alpha, chr){ 
    # your code for task a) and b) 
    UL = median(x, na.rm = TRUE) + alpha*IQR(x, na.rm = TRUE) 
    LL = median(x, na.rm = TRUE) - alpha*IQR(x, na.rm = TRUE) 
    Zoutliers <- which(x > UL | x < LL) 
    # part (c 
    # factor which specifies the direction. 0 values are set as positives 
    pos_neg <- ifelse(x[Zoutliers] >= 0, "positive", "negative") 
    # count the occurrence per chromosome and direction. 
    aggregate(x[Zoutliers], list(chr[Zoutliers], pos_neg), length) 
} 

# apply over the columns and get a list of dataframes with number of outliers per chr and direction. 
apply(d[,3:ncol(d)], 2, foo, 0.95, d$chr) 
+1

Fyi, il pacchetto ora offre la funzione 'fread' che puoi usare per leggere in testo come 'DT = fread (" testo testo ")' – Frank

+0

@Frank Oh, buono a sapersi. Inclusa questa funzione nella mia risposta. – Jimbou