2016-09-19 56 views
0

我有兩個列名稱向量。除一個數字外,每個矢量具有相同的長度和相同的名稱。使用if狀態有效循環遍歷行和列

columns <- paste0("q1h10_",1:9) # Filter columns 
columns2 <- paste0("q1h4_", 1:9) # Columns where number is at 

我想通過數據幀的行和通過列環在向量中的一個,每當有一個如圖5所示,發現在第二矢量的等效柱和帶來它的數量。我還有其他一些條件可以在下面的代碼中看到你可以看到的數字。

value <- vector("numeric", nrow(psid)) 

for (i in 1:nrow(psid)) { 
for (x in 1:length(columns)) { 
    if (5 %in% psid[i, columns[x]] & all(as.numeric(psid[i, columns2[x]]) != 97:99)) { 
     value[i] <- substr(columns[x], 7, 8) 
    } else if (5 %in% psid[i, columns[x]] & psid[i, columns2[x]] %in% 97:99 & x != 1) { 
     value[i] <- substr(columns[x - 1], 7, 8) 
    } else if (5 %in% psid[i, columns[x]] & psid[i, columns2[x]] %in% 97:99 & x == 1) { 
     value[i] <- 0 
    } 
    } 
} 
value 
[1] "1" "2" "2" "3" "4" "0" "0" "0" "1" "0" "3" "1" "3" "2" "3" "0" "1" "3" "1" "1" "2" 
[22] "2" "2" "1" "2" "3" "1" "1" "0" "1" 

我設法得到我想要的結果,但我覺得這是實現它的一個緩慢的方式。我已經嘗試過向申請家庭「傳授」,但我並不完全是專家,我無法正確地做到這一點。如果任何人有一個更快,也許更可讀的解決方案,任何幫助,將不勝感激。

數據:

psid <- structure(list(q1h10_1 = c(5L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 5L, 
0L, 1L, 5L, 1L, 1L, 1L, 0L, 5L, 1L, 5L, 5L, 1L, 1L, 1L, 5L, 1L, 
1L, 5L, 1L, 0L, 5L), q1h10_2 = c(0L, 5L, 5L, 1L, 1L, 0L, 0L, 
0L, 0L, 0L, 1L, 0L, 1L, 5L, 1L, 0L, 0L, 1L, 0L, 0L, 5L, 5L, 5L, 
0L, 5L, 1L, 0L, 5L, 0L, 0L), q1h10_3 = c(0L, 0L, 0L, 5L, 1L, 
0L, 0L, 0L, 0L, 0L, 5L, 0L, 5L, 0L, 5L, 0L, 0L, 5L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 5L, 0L, 0L, 0L, 0L), q1h10_4 = c(0L, 0L, 0L, 
0L, 5L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), q1h10_5 = c(0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), q1h10_6 = c(0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), q1h10_7 = c(0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), q1h10_8 = c(0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), q1h10_9 = c(0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), q1h4_1 = c(1, 
2, 6, 4, 4, 0, 0, 0, 4, 0, 3, 4, 4, 4, 1, 0, 4, 4, 3, 1, 4, 6, 
4, 4, 4, 4, 4, 3, 0, 6), q1h4_2 = c(0, 3, 4, 3, 3, 0, 0, 0, 0, 
0, 2, 0, 6, 4, 6, 0, 0, 4, 0, 0, 6, 4, 4, 0, 6, 6, 0, 97, 0, 
0), q1h4_3 = c(0, 0, 0, 6, 2, 0, 0, 0, 0, 0, 6, 0, 6, 0, 6, 0, 
0, 6, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0), q1h4_4 = c(0, 0, 0, 
0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0), q1h4_5 = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), q1h4_6 = c(0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0), q1h4_7 = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
), q1h4_8 = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), q1h4_9 = c(0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0)), class = "data.frame", .Names = c("q1h10_1", 
"q1h10_2", "q1h10_3", "q1h10_4", "q1h10_5", "q1h10_6", "q1h10_7", 
"q1h10_8", "q1h10_9", "q1h4_1", "q1h4_2", "q1h4_3", "q1h4_4", 
"q1h4_5", "q1h4_6", "q1h4_7", "q1h4_8", "q1h4_9"), row.names = c(NA, 
-30L)) 
+1

你能後的預期結果? – Sotos

回答

2

我們可以通過有效地執行你的邏輯更多的(你可以很容易地適應它的兩個人) :

value <- as.character(rep(0,nrow(psid))) 

cond1 <- 5 == psid[,columns] 
cond2 <- matrix(as.matrix(psid[,columns2]) %in% (97:99), nrow(psid)) 
ind1 <- which(cond1 & !cond2, arr.ind=TRUE) 
if (length(ind1) > 0) value[ind1[,1]] <- substr(columns[ind1[,2]],7,8) 
ind2 <- which(cond1 & cond2, arr.ind=TRUE) 
ind2 <- matrix(ind2[ind2[,2]!=1,],ncol=2) 
if (length(ind2) > 0) value[ind2[,1]] <- substr(columns[ind2[,2]-1],7,8) 

我們首先計算兩個bool「矩陣」:

  1. cond1TRUEi行和如果psid[i, columns[x]] == 5x; FALSE否則。該計算在psidcolumns的所有行和所有列上被矢量化。
  2. cond2TRUEi行和列x如果psid[i, columns2[x]]要麼9798,或99。在這裏,我們將psid[,columns2]轉換爲矩陣,然後評估其元素是否爲%in% (97:99)。然後將結果重新映射回原始尺寸的矩陣。

條件cond1 & !cond2是在您的第一個if條件。一旦我們對psid中的所有行和所有列進行了評估,我們可以使用whicharr.ind=TRUE來檢索此條件爲TRUE的行和列索引。然後,我們使用這些行和列進行子集相應地設置value

爲條件在你第一次elseif,我們進一步從which(cond1 & cond2, arr.ind=TRUE)只保留那些沒有1列(或x)子集的結果。再次,我們然後使用這些行和列進行子集相應地設置value

對於這兩個條件的補充,我們將value作爲"0"。請注意0​​可以返回一個空的結果(即length(0)),我們必須檢查該條件爲邊緣情況。

使用你的數據,結果不出所料:

print(value) 
## [1] "1" "2" "2" "3" "4" "0" "0" "0" "1" "0" "3" "1" "3" "2" "3" "0" "1" "3" "1" "1" "2" "2" 
##[23] "2" "1" "2" "3" "1" "1" "0" "1" 
+0

我猜'purr :: reduce'可以被'Reduce'取代嗎?另外,%(97:99)'中的'psid [,columns2]%可以更加方便,並且(至少在線性掃描數量極少的情況下)效率更高。 –

+0

@alexis_laz:感謝您的反饋。我相信,如果我們將數據幀轉換爲矩陣,然後按照您的建議使用'%in%',則不需要'reduce'。 – aichao

+0

你說得對,它需要轉換,我錯過了'psid'是一個「data.frame」。那麼我想,也可以先轉換爲「矩陣」,這將有利於所有二元運算。 –

0

我認爲下面的代碼正在爲你的第一個條件

ind=apply(psid,1,function(x) return(which(x[columns] %in% 5 & all(as.numeric(x[columns2]) !=97:99)))) 
values2=rep("0",nrow(psid)) 
values2[which(ind>0)]=substr(columns[unlist(ind[which(ind>0)])], 7, 8) 
values2 
[1] "1" "2" "2" "3" "4" "0" "0" "0" "1" "0" "3" "1" "3" "2" "3" 
[16] "0" "1" "3" "1" "1" "2" "2" "2" "1" "2" "3" "1" "2" "0" "1"