2016-10-19 29 views
5

Tôi đang cố tạo ma trận trang web và thời gian sự kiện. Trong trường hợp của tôi, một khi sự kiện đã xảy ra ("1") nó là vĩnh viễn và không thể quay trở lại một "0". Khi một ô trong một cột là "1", tôi đang cố gắng đưa ô liền kề vào các cột tiếp theo sang phải bằng dấu "1" (xem ví dụ dưới đây).R dplyr: Tìm một giá trị cụ thể trong một cột, sau đó thay thế ô liền kề trong các cột tiếp theo sang bên phải với giá trị đó

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 

Tôi đã tìm thấy một số mã đầy hứa hẹn sử dụng dplyr ví dụ: (Replacing more than one elements with replace function hoặc Apply function to each column in a data frame observing each columns existing data type) thay thế giá trị, mặc dù tôi không chắc chắn về cách chỉ định ô liền kề trong đối số cột tiếp theo.

Lời xin lỗi của tôi nếu câu hỏi này không rõ ràng, đây là bài đăng đầu tiên của tôi trên StackOverflow.

Cảm ơn bạn.

Trả lời

3

Thật ngạc nhiên khi bài đăng của người dùng đầu tiên được chi tiết, có thể tái tạo và thú vị, +1!

Với na.locf từ zoo gói bạn có thể làm:

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

Cảm ơn Osssan, tôi chưa bao giờ nghe nói về gói 'vườn thú', đây chính xác là những gì tôi cần. Đây là tất cả những câu trả lời thực sự tuyệt vời, tôi thích nhìn thấy tất cả những cách khác nhau mà bạn có thể làm tương tự :) – CarlaBirdy

1

Một cách tiếp cận base R sử dụng apply.

Về cơ bản, đối với mỗi hàng chúng tôi đang cố gắng tìm bất kỳ phần tử nào có 1 phần tử và gán 0 cho mọi phần tử ở bên trái của nó và 1 cho mọi phần tử ở bên phải.

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

Cảm ơn câu trả lời của bạn Ronak. Tôi thích nhìn thấy tất cả các cách khác nhau bạn có thể làm điều tương tự. Tôi không có nhiều kinh nghiệm sử dụng chức năng áp dụng, đó là điều tôi hy vọng sẽ cải thiện vì vậy cảm ơn bạn đã giúp tôi với điều này :) – CarlaBirdy

+0

@CarlaBirdy Tuyệt vời để biết rằng đó là một số trợ giúp. Bạn có thể chấp nhận bất kỳ câu trả lời nào ở đây. Kiểm tra [this] (http://stackoverflow.com/help/someone-answers) –

0

Đây là phương pháp R cơ sở thứ hai (không bao gồm định dạng lại). Điều này sử dụng applycummax (tối đa tích lũy). Nếu chỉ có một sự kiện xảy ra cho mỗi trang web, thì thay thế cummax bằng cumsum sẽ trả về cùng một kết quả.

# 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) 

này trả

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 

Lưu ý: Các định hình lại (với cast) cũng có thể được thực hiện với các cơ sở R reshape chức năng, nhưng bạn phải cũng sắp xếp lại các biến sau đó. Ví dụ:

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

sẽ tạo ra khung dữ liệu dự kiến.

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 Cảm ơn. Tôi đã không kiểm tra kết quả của 'reshape' đủ chặt chẽ. – lmo

+0

Tôi thích nhìn thấy tất cả các cách khác nhau mà bạn có thể làm tương tự. Cảm ơn bạn đã trả lời, tôi mong muốn được xem xét tất cả các loại mã khác nhau ngay hôm nay :) – CarlaBirdy

Các vấn đề liên quan