2015-05-15 22 views
15

Chciałbym wykluczyć wszystkie zduplikowane wiersze. Jednak musi to być prawda, gdy są to kolejne wiersze. Wynika reprezentatywnego przykładu:Wyklucz kolejne powielone wiersze

mój wkład df:

df <- "NAME VALUE 
    Prb1 0.05 
    Prb2 0.05 
    Prb3 0.05 
    Prb4 0.06 
    Prb5 0.06 
    Prb6 0.01 
    Prb7 0.10 
    Prb8 0.05" 

df <- read.table(text=df, header=T) 

My oczekiwany outdf:

outdf <- "NAME VALUE 
Prb1 0.05 
Prb4 0.06 
Prb6 0.01 
Prb7 0.10 
Prb8 0.05" 

outdf <- read.table(text=df, header=T) 

Odpowiedz

14

rle() to fajna funkcja, która identyfikuje przebiegi o identycznych wartościach, ale może to być rodzaj bólu, aby zmagać się z wynikami w użytecznej formie. Oto bezbolesna inkantacja, która działa w twoim przypadku.

df[sequence(rle(df$VALUE)$lengths) == 1, ] 
# NAME VALUE 
# 1 Prb1 0.05 
# 4 Prb4 0.06 
# 6 Prb6 0.01 
# 7 Prb7 0.10 
# 8 Prb8 0.05 
10

Prawdopodobnie istnieje wiele sposobów rozwiązywania tego, chciałbym spróbować rleid/unique kombinacji z data.tabledevel version

library(data.table) ## v >= 1.9.5 
unique(setDT(df)[, indx := rleid(VALUE)], by = "indx") 
# NAME VALUE indx 
# 1: Prb1 0.05 1 
# 2: Prb4 0.06 2 
# 3: Prb6 0.01 3 
# 4: Prb7 0.10 4 
# 5: Prb8 0.05 5 

Albo z jakiejś wielkiej sugestie od opinii:

używając tylko nowego shift funkcję

setDT(df)[VALUE != shift(VALUE, fill = TRUE)] 

lub korzystając duplicated połączeniu z rleid

setDT(df)[!duplicated(rleid(VALUE)), ] 
8

Jak o tym:

> df[c(T, df[-nrow(df),-1] != df[-1,-1]), ] 
    NAME VALUE 
1 Prb1 0.05 
4 Prb4 0.06 
6 Prb6 0.01 
7 Prb7 0.10 
8 Prb8 0.05 

W tym miejscu df[-nrow(df),-1] != df[-1,-1] znajduje pary kolejnych wierszy zawierających różne wartości, a reszta kodu wyodrębnia je z ramki danych.

2

natknąłem ten miły funkcji jakiś czas temu, które flagi rzędach jako pierwszy opiera się na określonej zmiennej:

isFirst <- function(x,...) { 
     lengthX <- length(x) 
     if (lengthX == 0) return(logical(0)) 
     retVal <- c(TRUE, x[-1]!=x[-lengthX]) 
     for(arg in list(...)) { 
      stopifnot(lengthX == length(arg)) 
      retVal <- retVal | c(TRUE, arg[-1]!=arg[-lengthX]) 
     } 
     if (any(missing<-is.na(retVal))) # match rle: NA!=NA 
      retVal[missing] <- TRUE 
     retVal 
    } 

stosując ją do swoich danych daje:

> df$first <- isFirst(df$VALUE) 
> df 
    NAME VALUE first 
1 Prb1 0.05 TRUE 
2 Prb2 0.05 FALSE 
3 Prb3 0.05 FALSE 
4 Prb4 0.06 TRUE 
5 Prb5 0.06 FALSE 
6 Prb6 0.01 TRUE 
7 Prb7 0.10 TRUE 
8 Prb8 0.05 TRUE 

You może następnie odfiltrować w pierwszej kolumnie, aby uzyskać oczekiwany wynik.

Znalazłem to bardzo przydatne w przeszłości, szczególnie z tła SAS, gdzie było to bardzo łatwe do zrobienia.

4

użyłbym rozwiązanie podobne do @NPE „s

df[c(TRUE,abs(diff(df$VALUE))>1e-6),] 

Oczywiście można użyć dowolnego innego poziomu tolerancji (inne niż 1e-6).

2

Wiele dobrych odpowiedzi już tutaj jest dplyr wersja:

filter(df,VALUE!=lag(VALUE,default=df$VALUE[1]+1))