2016-03-17 12 views
5

Ho questo set di dati che sto cercando di trasformare per ottenere le posizioni "da" e "a" all'interno di un particolare raggruppamento di punti dati che superano un test.estrazione prima e ultima posizione in un set di dati

Ecco come i dati appare:

pos <- seq(from = 10, to = 100, by = 10) 
test <- c(1, 1, 1, 0, 0, 0, 1, 1, 1, 0) 
df <- data.frame(pos, test) 

Così si può vedere che le posizioni 10, 20, e 30, così come il 70, 80, e 90, superare il test (b/c test = 1) ma il resto dei punti no. La risposta che sto cercando potrebbe essere un frame di dati che sembra qualcosa di simile alla data frame "risposta" nel seguente codice:

peaknum <- c(1, 2) 
from <- c(10, 70) 
to <- c(30, 90) 
answer <- data.frame(peaknum, from, to) 

Qualche suggerimento su come posso trasformare il set di dati? Sono perplesso.

Grazie, Steve

risposta

5

Possiamo usare data.table. Utilizzare la funzione rleid per creare gli ID del gruppo di run-length ('peaknum') in base ai valori adiacenti che sono lo stesso 'test'. Usando 'peaknum' come variabile di raggruppamento, otteniamo 'min' e 'max' di 'pos', mentre specificando 'i' come 'test == 1' per sottoporre a serie le righe. Se necessario, i valori di "peaknum" possono essere modificati nella sequenza ('seq_len (.N) `).

library(data.table) 
setDT(df)[, peaknum:= rleid(test)][test==1, 
    list(from=min(pos), to=max(pos)) ,peaknum][, peaknum:= seq_len(.N)] 
# peaknum from to 
#1:  1 10 30 
#2:  2 70 90 
+2

Questo ha funzionato perfettamente. Mi fa pensare che dovrei imparare data.table ad un certo punto :-) – Steven

+0

@Steven, saprai se è per te o no spendendo ~ 10-15 minuti su [Introduzione a data.table] (https://github.com/Rdatatable/data.table/wiki/Getting-started) vignetta. – Arun

3

Possiamo farlo con dplyr, anche se la separazione dei nodi è un po 'brutto:

library(dplyr) 
df %>% group_by(peaknum = rep(seq(rle(test)[['lengths']]), rle(test)[['lengths']])) %>% 
    filter(test == 1) %>% 
    summarise(from = min(pos), 
      to = max(pos)) %>% 
    mutate(peaknum = seq_along(peaknum)) 

# Source: local data frame [2 x 3] 

# peaknum from to 
#  (int) (dbl) (dbl) 
# 1  1 10 30 
# 2  2 70 90 

Cosa fa:

  • il primo group_by utilizza rle aggiungere una colonna che è una sequenza lungo i numeri ripetuti in test e raggrupparla per summarise più tardi;
  • filter costolette righe giù a solo quelle in cui è test1
  • summarise crolla gruppi e aggiunge max e min per ciascuno,
  • ed infine mutate pulisce la numerazione di peaknum.
+0

Oppure caricare data.table accanto a dplyr e utilizzare rleid per il primo passaggio. – Frank

+0

Sì, questo lo renderebbe molto più carino. – alistaire

Problemi correlati