2016-12-04 86 views
1

我知道已經發布了很多問題,但我無法將解決方案應用於我的問題。如果條件滿足,則跳到下一行,然後再檢查另一個條件

我有一個包含許多行和列的數據集。下面是一個示例:

V7 V8 V9 
0 1 0 
-1 1 -1 
-1 1 -1 
-1 0 -1 
-1 0 -1 
-1 0 -1 
-1 0 -1 
-1 1 -1 
0 1 -1 
0 1 -1 
-1 0 0 
0 0 0 
0 0 0 
0 0 0 
0 0 0 
0 -1 0 
0 -1 -1 
0 0 0 
0 1 0 
0 0 0 

該數據被保存在一個矩陣trboot3 我想要做的就是創建一個循環,其中兩個條件檢查和數據被改變。

  1. 如果有零,則跳至下一行。
  2. 如果一行中的第一個數字相同,則保留第一個數字並將其餘數字改爲零。

這裏是我上面的循環代碼:

trboot4<-trboot3 
valboot<-length(trboot3[,1]) 
for (k in 1:length(trboot3[1,])){ 
    for (i in 2:valboot-1){ 
    if (trboot3[k,i]==0) {i<-i+1} 
    else{ 
     if(trboot3[k,i] == trboot3[k,i+1]){ 
     for (j in i+1:valboot){ if(trboot3[k,j] == trboot3[k,i]){trboot4[k,j]<-0}else{break} 
      if(j==valboot){break} 
     } 
     } 
    } 
    } 
} 

我要保存新的矩陣trboot4

基本上上面的示例應該變成:

V7 V8 V9 
0 1 0 
-1 0 -1 
0 0 0 
0 0 0 
0 0 0 
0 0 0 
0 0 0 
0 1 0 
0 0 0 
0 0 0 
-1 0 0 
0 0 0 
0 0 0 
0 0 0 
0 0 0 
0 -1 0 
0 0 -1 
0 0 0 
0 1 0 
0 0 0 
+0

是否電流回路工作?如果有效,它是否太慢? – digEmAll

+0

嗨@digEmAll除當前循環的'下標越界外'沒有錯誤。但是我的trboot4輸出與trboot3相同。不,至少對我來說不是很慢。 – miababy

+0

我已經提供了一個不使用循環的解決方案,順便說一句,你可以使用nrow和ncol函數來獲得矩陣的行數和列數,你不需要這樣做:'length(m [,1])'etc ... – digEmAll

回答

3

你可以使用rleapply功能:

# re-create your matrix 
trboot3 <- structure(c(0,-1,-1,-1,-1,-1,-1,-1,0,0,-1,0,0,0,0,0,0,0,0,0,1,1,1, 
0,0,0,0,1,1,1,0,0,0,0,0,-1,-1,0, 1,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,0,0, 
-1,0,0,0),.Dim = c(20L, 3L), .Dimnames = list(NULL, c("V7", "V8", "V9"))) 

keepFirstValueIfRepeated <- function(v){ 
    RLE <- rle(v) 
    firstIndex <- (cumsum(RLE$lengths)- RLE$lengths + 1) 
    v2 <- rep.int(0,length(v)) 
    v2[firstIndex] <- RLE$values 
    return(v2) 
} 

trboot4 <- apply(trboot3,2,FUN=keepFirstValueIfRepeated) 

結果:

> trboot4 
     V7 V8 V9 
[1,] 0 1 0 
[2,] -1 0 -1 
[3,] 0 0 0 
[4,] 0 0 0 
[5,] 0 0 0 
[6,] 0 0 0 
[7,] 0 0 0 
[8,] 0 1 0 
[9,] 0 0 0 
[10,] 0 0 0 
[11,] -1 0 0 
[12,] 0 0 0 
[13,] 0 0 0 
[14,] 0 0 0 
[15,] 0 0 0 
[16,] 0 -1 0 
[17,] 0 0 -1 
[18,] 0 0 0 
[19,] 0 1 0 
[20,] 0 0 0 

說明:

讓我們從第一個自定義功能keepFirstValueIfRepeated它得到一個向量v,並保持連續相等值的序列只有第一個值開始,迫使其他人歸零。
它是如何實現的?

我們使用rle函數,它對分析連續相等值的子序列非常有用,事實上它返回一個列表,其中包含子序列的長度和每個子序列的重複值。
這個想法是隻保留重複值的子序列的第一個元素;首先,我們計算包含子序列第一個元素的所有索引的firstIndex,然後我們創建一個長度爲v但具有全零的矢量v2,最後我們將子的第一個值v2內部的序列。

在此之後,我們需要這個功能(keepFirstValueIfRepeated)「應用」於trboot3每一列,而這正是apply(matrix,2,FUN)

+0

嗨@digEmAll我可以麻煩你解釋如何在這種情況下rle函數工作嗎?謝謝 – miababy

+0

是的,我這樣做;) – digEmAll

+0

謝謝你,因爲我必須進一步編碼,並可能最終使用類似的代碼,因爲循環不工作 – miababy

1

另一種解決方案:

library(Hmisc) 
trboot4 = apply(trboot3, 2, function(c) c * (c!=Lag(c))) 
trboot4[1,] = trboot3[1,] 
+0

你好!你能解釋一下Lag()函數是如何工作的嗎?謝謝 – miababy

相關問題