2016-12-21 5 views
3

私はhousehold gridとして知られている調査で一般的に見られるものを扱っています。 household gridは、世帯のメンバー間の関係を示します。私はここで1r - 世帯のグリッドでカップルIDを取得

houseID id sex age relto1 relto2   relto3   relto4 
1  1 1 male 45  0 spouse not applicable not applicable 
2  1 2 female 38 spouse  0 not applicable not applicable 
3  2 1 female 18  0 daughter  daughter not applicable 
4  2 2 male 50 parent  0   spouse not applicable 
5  2 3 female 45 parent spouse    0 not applicable 
6  3 1 female 45  0 parent   parent   spouse 
7  3 2 male 17 son  0  brother   son 
8  3 3 male 19 son brother    0   son 
9  3 4 male 50 spouse parent   parent    0 

houseIDを再現しようとした

が一意家庭識別子、家庭のmembresのid固有のIDであり、relto_は、各家庭用idの関係を示します。

id == 1最初家庭用 id == 2spouseであることを意味 例えば

行1relto2 == spouse

私は配偶者の識別子を取得することに興味があります。 トリックは、spouse idが常に同じ位置にあるわけではないということです。世帯数4で

、配偶者は私がこの1

あるまで来ることができました。この

houseID id sex age spousenum 
1  1 1 male 45   2 
2  1 2 female 38   1 
3  2 1 female 18   0 
4  2 2 male 50   3 
5  2 3 female 45   2 
6  3 1 female 45   4 
7  3 2 male 17   0 
8  3 3 male 19   0 
9  3 4 male 50   1 

最高のコードを実行することですに興味を持って何id 1と4

であります

dtsp = df[, grepl('rel', colnames(df)) ] 

# not too long, its fine # 
for(i in 1:nrow(dtsp)){ 
    for(j in 1:ncol(dtsp)){ 
    if(dtsp[i, j] == 'spouse'){ 
     df[i,'spousenum'] <- j 
    } 
    } 
} 

しかし、それは少しばかげて遅いようです。

もっと効率的なコードをお探しですか?

データ

df = rbind(c('1', '1', 'male', '45', '0', 'spouse', 'not applicable', 'not applicable'), 
     c('1', '2', 'female', '38', 'spouse', '0', 'not applicable', 'not applicable'), 
     c('2', '1', 'female', '18', '0', 'daughter', 'daughter', 'not applicable'), 
     c('2', '2', 'male', '50', 'parent', '0', 'spouse', 'not applicable'), 
     c('2', '3', 'female', '45', 'parent', 'spouse', '0', 'not applicable'), 
     c('3', '1', 'female', '45', '0', 'parent', 'parent', 'spouse'), 
     c('3', '2', 'male', '17', 'son', '0', 'brother', 'son'), 
     c('3', '3', 'male', '19', 'son', 'brother', '0', 'son'), 
     c('3', '4', 'male', '50', 'spouse', 'parent', 'parent', '0')) 

df = as.data.frame(df) 
colnames(df) = c('houseID', 'id', 'sex', 'age', 'relto1', 'relto2', 'relto3', 'relto4') 

答えて

1

は、我々はmax.colで簡単にこれを行うことができます。 (grepを使用して)データセットの 'relt'列をサブセット化し、max.colで論理行列を作成し、rowSumsを掛けてTRUE値のTRUE値のfirstインデックスを見つけ、TRUE値がない場合は0になり、 cbindには、データセットの非リレーショナル列が含まれています。 「RN」に変換する

i1 <- grep("relt", colnames(df1)) 
m1 <- df1[i1] == "spouse" 
cbind(df1[-i1], spousenum = max.col(m1, "first")*rowSums(m1)) 
# houseID id sex age spousenum 
#1  1 1 male 45   2 
#2  1 2 female 38   1 
#3  2 1 female 18   0 
#4  2 2 male 50   3 
#5  2 3 female 45   2 
#6  3 1 female 45   4 
#7  3 2 male 17   0 
#8  3 3 male 19   0 
#9  3 4 male 50   1 

我々はdplyr/tidyr家族のソリューションに興味がある場合は、tibble::rownames_to_columnでrowname列を作成、gatherと「長い」形式に再構築、filterのみ「配偶者」行、transmute列にnumericを入力し、 'spousenum'を作成するために 'relt'から数字部分を抽出し、completefull_seqtidyr)を使用して、 'spousenum'を0で塗りつぶしながら 'rn'の完全シーケンスを作成し、データセット。

library(dplyr) 
library(tidyr) 
library(tibble) 
rownames_to_column(df1, var = "rn") %>% 
      gather(relt, val, relto1:relto4) %>% 
      filter(val == "spouse") %>% 
      transmute(rn = as.numeric(rn), spousenum = as.numeric(sub("\\D+", "", relt))) %>% 
      complete(rn = full_seq(rn, 1), fill = list(spousenum=0)) %>% 
      select(-rn) %>% 
      bind_cols(df1, .) %>% 
      select(-matches("relt")) 
# houseID id sex age spousenum 
#1  1 1 male 45   2 
#2  1 2 female 38   1 
#3  2 1 female 18   0 
#4  2 2 male 50   3 
#5  2 3 female 45   2 
#6  3 1 female 45   4 
#7  3 2 male 17   0 
#8  3 3 male 19   0 
#9  3 4 male 50   1 
+1

は精巧な答えてくれてありがとう – giacomo

1

これを試してみてください:

df$spousenum = apply(df[,5:8], 1, function(r) which(r=='spouse')[1]) 
関連する問題