2016-09-19 12 views
0

私は列名のベクトルを2つ持っています。各ベクトルは同じ長さであり、単一の数字を除いて同じ名前です。if文を使って効率的に行と列をループする

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

Iはベクトル一列のデータフレームの列を通って貫通ループ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) 

まず、2つのブール「行列」を計算します。

  1. iおよび列xpsid[i, columns[x]] == 5場合にTRUEあります。それ以外の場合はFALSEです。この計算は、columnsのすべての行とすべての列に対してベクトル化され、psidです。
  2. cond2いずれか9798、又は99あるxpsid[i, columns2[x]]場合行iと列でTRUEあります。ここではpsid[,columns2]を行列に変換し、その要素が%in% (97:99)かどうかを評価します。結果は元の寸法の行列に再整形されます。

条件cond1 & !cond2は、最初のifの条件です。私たちはこのpsid内のすべての行とすべての列を評価した後、私たちは、この条件がTRUEされた行と列のインデックスを取得するためにarr.ind=TRUEwhichを使用することができます。これらの行と列を使用してサブセットを作成し、それに応じてvalueを設定します。あなたの最初のelseifにおける条件については

、我々はさらに1でない列のみ(またはx)を保つことによってwhich(cond1 & cond2, arr.ind=TRUE)から結果をサブセット。ここでも、これらの行と列を使用してサブセットを設定し、それに応じてvalueを設定します。これらの2つの条件の補数のために

、我々は"0"としてvalueを残します。 whichは空の結果(つまり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'で置き換えられますか?また、 'psid [、columns2]%in%(97:99)'は、より効率的で(少なくとも、線形スキャンがごく少数の場合)、より効率的です。 –

+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" 
関連する問題