2016-10-19 44 views
5

Próbuję utworzyć macierz witryny i czasu zdarzenia. W moim przypadku, gdy zdarzenie miało miejsce ("1"), jest trwałe i nie może wrócić do "0". Gdy komórka w kolumnie ma wartość "1", próbuję wypełnić sąsiednią komórkę w kolejnych kolumnach po prawej stronie za pomocą "1" (patrz przykład poniżej).R dplyr: Znajdź konkretną wartość w kolumnie, a następnie zastąp sąsiednią komórkę w kolejnych kolumnach po prawej stronie o tej wartości

site <- c('A','B','C','D','E','F','G') #site 
time <- c(0,1,4,0,3,2,0) # time in which even occured 
event <- c(0,1,1,0,1,1,0) # did a event occur 
data <- data.frame(site, time, event) 

site.time.matrix <- cast(data, site~time) 

# This is the output  # This is the desired output 
#site 0 1 2 3 4  #site 0 1 2 3 4 
# A 0 NA NA NA NA  # A 0 0 0 0 0 
# B NA 1 NA NA NA  # B 0 1 1 1 1 
# C NA NA NA NA 1  # C 0 0 0 0 1 
# D 0 NA NA NA NA  # D 0 0 0 0 0 
# E NA NA NA 1 NA  # E 0 0 0 1 1 
# F NA NA 1 NA NA  # F 0 0 1 1 1 
# G 0 NA NA NA NA  # G 0 0 0 0 0 

Znalazłem obiecujący kod za pomocą dplyr np. (Replacing more than one elements with replace function lub Apply function to each column in a data frame observing each columns existing data type), która zastępuje wartości, chociaż nie jestem pewien, jak określić sąsiednią komórkę w kolejnych argumentach kolumn.

Moje przeprosiny, jeśli to pytanie jest niejasne, to mój pierwszy wpis na StackOverflow.

Dziękuję.

Odpowiedz

3

Było miło zaskoczyć, że pierwszy post użytkownika będzie szczegółowy, powtarzalny i interesujący, +1!

Z na.locf z zoo pakietu można zrobić:

library(reshape) # for cast function 
library(zoo) #for na.locf function short for if NA, last observation carrried forward, ?na.locf 

site <- c('A','B','C','D','E','F','G') #site 
time <- c(0,1,4,0,3,2,0) # time in which even occured 
event <- c(0,1,1,0,1,1,0) # did a event occur 
data <- data.frame(site, time, event) 

site.time.matrix <- reshape::cast(data, site~time) 

site.time.matrix.fill <- site.time.matrix 


# Transpose the matrix excluding first column, carry forward last observation and 
# transpose again to return to original matrix structure 

site.time.matrix.fill[,-1] <- t(na.locf(t(site.time.matrix.fill[,-1]))) 

site.time.matrix.fill[is.na(site.time.matrix.fill)] <- 0 

site.time.matrix.fill 

# site 0 1 2 3 4 
#1 A 0 0 0 0 0 
#2 B 0 1 1 1 1 
#3 C 0 0 0 0 1 
#4 D 0 0 0 0 0 
#5 E 0 0 0 1 1 
#6 F 0 0 1 1 1 
#7 G 0 0 0 0 0 
+0

Dziękuję Osssan, nigdy nie słyszałem o pakiecie "zoo", to jest dokładnie to, czego potrzebowałem. To są naprawdę świetne odpowiedzi, uwielbiam widzieć różne sposoby na zrobienie tego samego :) – CarlaBirdy

1

base R podejście używając apply.

Zasadniczo dla każdego wiersza próbujemy znaleźć dowolny element, który ma 1 i przypisuje 0 do każdego elementu po lewej stronie i 1 do każdego elementu po prawej stronie.

t(apply(site.time.matrix, 1, function(x) { 
     temp = if(any(x == 1, na.rm = T)) which(x==1)-1 else length(x) 
     x[temp:length(x)] <- 1 
     x[0:temp] <- 0 
     x 
})) 


# 0 1 2 3 4 
#A 0 0 0 0 0 
#B 0 1 1 1 1 
#C 0 0 0 0 1 
#D 0 0 0 0 0 
#E 0 0 0 1 1 
#F 0 0 1 1 1 
#G 0 0 0 0 0 
+1

Dziękuję za odpowiedź Ronak. Uwielbiam widzieć różne sposoby, w jakie możesz zrobić to samo. Nie mam zbyt dużego doświadczenia w korzystaniu z funkcji "Zastosuj", jest to coś, co mam nadzieję poprawić, więc dziękuję za pomoc mi w tym :) – CarlaBirdy

+0

@CarlaBirdy Wspaniale jest wiedzieć, że to było pomocne. Możesz zaakceptować jedną z odpowiedzi tutaj. Sprawdź [to] (http://stackoverflow.com/help/someone-answers) –

0

Oto druga podstawowa metoda R (z wyłączeniem zmiany kształtu). Używa to apply i cummax (maksimum skumulowane). Jeśli wystąpi tylko jedno zdarzenie dla każdej witryny, to zastąpienie cummax wartością cumsum spowoduje zwrócenie tego samego wyniku.

# reshape the data 
temp <- cast(data, site~time) 

# construct matrix of 0s and 1s 
myMat <- as.matrix(temp[-1]) 
myMat[is.na(myMat)] <- 0 

# expand 1s to the right when they appear 
myMat <- t(apply(myMat, 1, cummax)) 

# add row and column names 
dimnames(myMat) <- list(levels(temp$site), seq_len(ncol(myMat))-1) 

ta zwraca

myMat 
    0 1 2 3 4 
A 0 0 0 0 0 
B 0 1 1 1 1 
C 0 0 0 0 1 
D 0 0 0 0 0 
E 0 0 0 1 1 
F 0 0 1 1 1 
G 0 0 0 0 0 

UWAGA: przywracania kształtu (z cast) mogą być również wykonywane z bazy badawczo reshape funkcji, ale trzeba także zmienić kolejność zmienne później. Na przykład:

# reshape data 
temp <- reshape(data, direction="wide", idvar="site") 
# reorder variables 
temp <- temp[c("site", sort(names(temp)[-1]))] 

wytworzy oczekiwaną ramkę danych.

site event.0 event.1 event.2 event.3 event.4 
1 A  0  NA  NA  NA  NA 
2 B  NA  1  NA  NA  NA 
3 C  NA  NA  NA  NA  1 
4 D  0  NA  NA  NA  NA 
5 E  NA  NA  NA  1  NA 
6 F  NA  NA  1  NA  NA 
7 G  0  NA  NA  NA  NA 
+1

@RonakShah Dzięki. Nie sprawdziłem wystarczająco dokładnie wyników "zmiany kształtu". – lmo

+0

Uwielbiam widzieć na różne sposoby, jak możesz zrobić to samo. Dziękuję za odpowiedź, nie mogę się doczekać przejrzenia wszystkich różnych typów kodu dzisiaj :) – CarlaBirdy