2017-04-04 13 views
5

Próbuję znaleźć właściwą drogę w R, aby znaleźć powielone wartości i dodać wartość 1 do każdej kolejnej zduplikowanej wartości pogrupowanej według identyfikatora. Na przykład:Zwiększenie o jedną do każdej zduplikowanej wartości w R

data=data.table(id=c('1','1','1','1','1','2','2','2'),value=c(95,100,101,101,101,20,35,38)) 
data$new_value <- ifelse(data[,data$value] == lag(data$value,1), lag(data$value,1)+1 ,data$value) 
data$desired_value <- c(95,100,101,102,103,20,35,38) 

Produkuje:

id value new_value desired_value 
1: 1 95  NA   95 
2: 1 100  100   100 
3: 1 101  101   101 
4: 1 101  102   102 
5: 1 101  102   103 
6: 2 20  20   20 
7: 2 35  35   35 
8: 2 38  38   38 

Próbowałem robić to z ifelse ale to nie działa rekurencyjnie więc stosuje się tylko do następnego wiersza, a nie jakieś kolejne wiersze. Również funkcja lag powoduje, że tracę pierwszą wartość w value.

Widziałem przykłady ze zmiennymi znakowymi z make.names lub make.unique, ale nie udało mi się znaleźć rozwiązania dla zduplikowanej wartości liczbowej.

Kontekst: Przeprowadzam analizę przeżycia i stwierdzam, że z moimi danymi wynika, że ​​czasy zatrzymania są takie same, więc muszę je zmienić, dodając 1 (czasy zatrzymania podane są w sekundach).

Odpowiedz

6

Oto próba. W zasadzie grupujesz według id i value i dodajesz 0:(length(value)-1). Więc:

data[, onemore := value + (0:(.N-1)), by=.(id, value)] 

# id value new_value desired_value onemore 
#1: 1 95  96   95  95 
#2: 1 100  101   100  100 
#3: 1 101  102   101  101 
#4: 1 101  102   102  102 
#5: 1 101  102   103  103 
#6: 2 20  21   20  20 
#7: 2 35  36   35  35 
#8: 2 38  39   38  38 
+1

@akrun i @thelatemail widzę. Tak więc używamy "by" do grupowania, które .N obsługuje i staje się całkowitą liczbą obserwacji w tej grupie. "101" pojawia się 3 razy w id "1", .N = 3 lub '(0: (3-1))'. Daje to w wyniku "wartość + (0: 2)" lub po prostu "wartość + 0, wartość +1, wartość + 2". Dziękuję Ci! –

5

Z zasady R możemy użyć ave gdzie bierzemy pierwszą wartość każdej grupy i zasadniczo dodać numer wiersza tego wiersza w tej grupie.

data$value1 <- ave(data$value, data$id, data$value, FUN = function(x) 
                 x[1] + seq_along(x) - 1) 

# id value new_value desired_value value1 
#1: 1 95  96   95  95 
#2: 1 100  101   100 100 
#3: 1 101  102   101 101 
#4: 1 101  102   102 102 
#5: 1 101  102   103 103 
#6: 2 20  21   20  20 
#7: 2 35  36   35  35 
#8: 2 38  39   38  38 
1

Oto jedna opcja z tidyverse

library(dplyr) 
data %>% 
    group_by(id, value) %>% 
    mutate(onemore = value + row_number()-1) 
#  id value onemore 
# <chr> <dbl> <dbl> 
#1  1 95  95 
#2  1 100  100 
#3  1 101  101 
#4  1 101  102 
#5  1 101  103 
#6  2 20  20 
#7  2 35  35 
#8  2 38  38 

Albo możemy użyć base R bez anonimowego wywołania funkcji

data$onemore <- with(data, value + ave(value, id, value, FUN =seq_along)-1) 
data$onemore 
#[1] 95 100 101 102 103 20 35 38 
+0

Jaki jest problem z rozwiązaniem? Dlaczego zaniedbanie uzasadnionego rozwiązania? – akrun

Powiązane problemy