2017-01-12 19 views
11
dummies = matrix(c(0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0), nrow=6, ncol=6) 
colnames(dummies) <- c("a","b", "c", "d", "e", "f") 

Tôi có một ma trận với núm vú cao suVectorisation của vòng lặp for với nhiều điều kiện

> dummies 
    a b c d e f 
[1,] 0 0 0 0 1 0 
[2,] 0 0 1 0 0 0 
[3,] 1 0 0 0 0 0 
[4,] 0 0 0 0 0 1 
[5,] 0 1 0 0 0 0 
[6,] 0 0 0 1 0 0 

Tôi biết rằng núm vú cao su của tôi có liên quan trong đó dòng 1 được nhóm với 2, 3 với 4, và 5 với 6 . tôi muốn chia mỗi mã giả (1) giữa những người trong cùng một nhóm trên cùng một dòng như trên:

> dummies 
     a b c d e f 
[1,] 0.0 0.0 -0.5 0.0 0.5 0.0 
[2,] 0.0 0.0 0.5 0.0 -0.5 0.0 
[3,] 0.5 0.0 0.0 0.0 0.0 -0.5 
[4,] -0.5 0.0 0.0 0.0 0.0 0.5 
[5,] 0.0 0.5 0.0 -0.5 0.0 0.0 
[6,] 0.0 -0.5 0.0 0.5 0.0 0.0 

để đạt được điều này, tôi thực hiện như sau:

dummies <- ifelse(dummies==1, 0.5, 0) 
for (i in 1:nrow(dummies)){ 
    column = which(dummies[i,] %in% 0.5) 
    if (i %% 2 != 0) {  
     dummies[i+1, column] <- -0.5 
    } else {    
     dummies[i-1, column] <- -0.5 
    } 
} 

Câu hỏi của tôi là liệu tôi có thể đạt được điều này với mã được vector hóa hay không. Tôi không thể tìm ra cách sử dụng ifelse trong trường hợp này vì tôi không thể kết hợp nó với chỉ mục dòng để tìm số 0.5 trên mỗi dòng.

Trả lời

12

Dưới đây là một nỗ lực trong cơ sở R

# get locations of ones 
ones <- which(dummies == 1) 
# get adjacent locations 
news <- ones + c(1L, -1L)[(ones %% 2 == 0L) + 1L] 

# fill out matrix 
dummiesDone <- dummies * 0.5 
dummiesDone[news] <- -0.5 

dummiesDone 
     a b c d e f 
[1,] 0.0 0.0 -0.5 0.0 0.5 0.0 
[2,] 0.0 0.0 0.5 0.0 -0.5 0.0 
[3,] 0.5 0.0 0.0 0.0 0.0 -0.5 
[4,] -0.5 0.0 0.0 0.0 0.0 0.5 
[5,] 0.0 0.5 0.0 -0.5 0.0 0.0 
[6,] 0.0 -0.5 0.0 0.5 0.0 0.0 

giải pháp này sử dụng thực tế là một ma trận đơn giản là một véc tơ với một thuộc tính kích thước. which tìm vị trí của 1 trong vector cơ bản.

cụm từ thứ hai trong dòng thứ hai, c(1, -1)[(ones %% 2 == 0L) + 1L] cho phép lựa chọn phần tử "cặp" của vectơ sẽ được sử dụng để chia các giá trị đó, dựa trên vị trí ban đầu hay không. Điều này hoạt động ở đây vì có một số hàng đồng đều, điều cần thiết trong vấn đề này của các phần tử được ghép nối.

Dòng tiếp theo điền vào ma trận dựa trên nguyên tố ban đầu là một (0,5) hay nếu nó là phần tử cặp liền kề (-0,5). Lưu ý rằng lệnh thứ hai khai thác khái niệm vị trí vectơ bên dưới.


Một phương pháp thứ hai mà mượn tắt của các khái niệm về bài viết và ý kiến ​​từ hubertl, thelatemail, và martin-morgan rằng trừ 0,5 từ ma trận ban đầu tại các địa điểm chính xác đầu tiên để có được các chỉ số tương tự như trên

# get locations of ones 
ones <- which(dummies == 1) 
# get adjacent locations 
news <- ones + c(1L, -1L)[(ones %% 2 == 0L) + 1L] 

và sau đó kết hợp với [<- trừ

dummies[c(ones, news)] <- dummies[c(ones, news)] - .5 
dummies 
     a b c d e f 
[1,] 0.0 0.0 -0.5 0.0 0.5 0.0 
[2,] 0.0 0.0 0.5 0.0 -0.5 0.0 
[3,] 0.5 0.0 0.0 0.0 0.0 -0.5 
[4,] -0.5 0.0 0.0 0.0 0.0 0.5 
[5,] 0.0 0.5 0.0 -0.5 0.0 0.0 
[6,] 0.0 -0.5 0.0 0.5 0.0 0.0 
+0

Câu trả lời 'Chấp nhận' được chọn dựa trên giải thích rõ ràng và chi tiết. Cảm ơn bạn. – Tony

5

Dưới đây là cách tiếp cận khác:

dummies[] <- sapply(split(dummies, gl(length(dummies)/2,2)), function(v) if(any(!!v))v-.5 else v) 
     a b c d e f 
[1,] 0.0 0.0 -0.5 0.0 0.5 0.0 
[2,] 0.0 0.0 0.5 0.0 -0.5 0.0 
[3,] 0.5 0.0 0.0 0.0 0.0 -0.5 
[4,] -0.5 0.0 0.0 0.0 0.0 0.5 
[5,] 0.0 0.5 0.0 -0.5 0.0 0.0 
[6,] 0.0 -0.5 0.0 0.5 0.0 0.0 
4

cách tiếp cận khác:

dummies - ((dummies[c(1,3,5),]+dummies[c(2,4,6),])/2)[c(1,1,2,2,3,3),] 

     a b c d e f 
[1,] 0.0 0.0 -0.5 0.0 0.5 0.0 
[2,] 0.0 0.0 0.5 0.0 -0.5 0.0 
[3,] 0.5 0.0 0.0 0.0 0.0 -0.5 
[4,] -0.5 0.0 0.0 0.0 0.0 0.5 
[5,] 0.0 0.5 0.0 -0.5 0.0 0.0 
[6,] 0.0 -0.5 0.0 0.5 0.0 0.0 
+2

Biến thể - '(núm vú giả - núm vú giả [c (2: 1,4: 3,6: 5),])/2' – thelatemail

6

Tạo một vector chỉ ra các nhóm hàng, grp, và trừ nhóm có nghĩa rowsum(dummies, grp)/2 từ mỗi thành viên trong nhóm, như

grp = rep(seq_len(nrow(dummies)/2), each=2) 
dummies - rowsum(dummies, grp)[grp,]/2 

Một chút hơn nói chung, cho phép các nhóm có kích thước khác nhau và không được đặt hàng

dummies - (rowsum(dummies, grp)/tabulate(grp))[grp,] 
Các vấn đề liên quan