4

繰り返し定義された計算を実行するのに問題があります。次のデータは例として役立ちます(実際のデータセットははるかに大きくなります)。

## DATA ##
# Columns
   Individual<-c("A","B","C","D","E","F","G","H1","H2","H3","H4","H5","K1","K2","K3","K4","K5")
   P1<-c(0,0,"A",0,"C","C",0, rep("E",5),"H1","H2","H3","H4","H5")
   P2<-c(0,0,"B",0,"D", "E",0,rep("G",5),"H1","H2","H3","H4","H5")
# Dataframe
   myd<-data.frame(Individual,P1,P2,stringsAsFactors=FALSE)


   Individual P1 P2
1           A  0  0
2           B  0  0
3           C  A  B
4           D  0  0
5           E  C  D
6           F  C  E
7           G  0  0
8          H1  E  G
9          H2  E  G
10         H3  E  G
11         H4  E  G
12         H5  E  G
13         K1 H1 H1
14         K2 H2 H2
15         K3 H3 H3
16         K4 H4 H4
17         K5 H5 H5

P1データは、と個人と2人の親の間の関係を表しP2ます。

ラベルが付けられた必要な計算は、relationA各個人がAにどの程度関連しているかを表します。

定義により、AとAの関係には1の値が与えられます。他のすべての個人の値は、次のように、表の情報に基づいて計算する必要があります。

The value of relationA for an individual should be equal to 
   1/2 (the value of relationA of P1 of the individual)  
 + 1/2 (the value of relationA of P2 of the individual)

例えば

  Individual P1 P2      relationA
1           A  0  0       1
2           B  0  0       0
3           C  A  B       (A = 1 + B = 0)/2 = 0.5
4           D  0  0       0
5           E  C  D       (C= 0.5 + D = 0)/2 = 0.25
6           F  C  E       (C = 0.5 + E = 0.25)/2 = 0.375  

期待される出力は次のとおりです。

 Individual P1 P2  relationA
1           A  0  0   1
2           B  0  0   0
3           C  A  B   0.5
4           D  0  0   0
5           E  C  D   0.25
6           F  C  E   0.375
7           G  0  0   0 
8          H1  E  G   0.125
9          H2  E  G   0.125
10         H3  E  G   0.125
11         H4  E  G   0.125
12         H5  E  G   0.125
13         K1 H1 H1   0.125
14         K2 H2 H2   0.125
15         K3 H3 H3   0.125
16         K4 H4 H4   0.125
17         K5 H5 H5   0.125

私の難しさは、これを適切な方法でで表現することですR。どんな助けでもいただければ幸いです。

4

2 に答える 2

4

個人と(暗黙的に)関係を与えられた値を単純な再帰関数として計算する関数を書くことができます。

relationA <- function(ind) {
  if(ind == "A") {
    1
  } else if (ind == "0") {
    0
  } else {
    pts <- myd[myd$Individual == ind,]
    (relationA(pts[["P1"]]) + relationA(pts[["P2"]])) / 2
  }
}

簡単に言うと、個人がAの場合、それは1です。個人が0の場合、それは0です。それ以外の場合は、個人に対応するrelationA各親(P1およびP2)を再帰的に呼び出し、それらを合計して2で割ります。これは一度に1人の個人に対してのみ機能します。

> relationA("A")
[1] 1
> relationA("F")
[1] 0.375
> relationA("K5")
[1] 0.125

しかし、比較的簡単にすべての個人にベクトル化できます。

> sapply(myd$Individual, relationA)
    A     B     C     D     E     F     G    H1    H2    H3    H4    H5    K1 
1.000 0.000 0.500 0.000 0.250 0.375 0.000 0.125 0.125 0.125 0.125 0.125 0.125 
   K2    K3    K4    K5 
0.125 0.125 0.125 0.125 

これはでに割り当てることができmydます

myd$relationA <- sapply(myd$Individual, relationA)

relationAケースごとに何度も計算する必要があるため、これは特に効率的ではありません。「K5」になると、reationA("H5")2回呼び出され、それぞれがとを呼び出し、relationA("E")それらrelationA("G")が、、、などrelationA("C")を呼び出します。つまり、結果はキャッシュされず、毎回再計算されます。この小さなデータセットの場合、非効率でも非常に高速であるため、問題ではありません。relationA("D")relationA("0")relationA("0")

結果をキャッシュしてそのキャッシュを使用する必要がある場合は、そのように変更できますrelationA

relationAc <- function(ind) {
  pts <- myd[myd$Individual == ind,]
  if(nrow(pts) == 0 | any(is.na(pts[["relationA"]]))) {
    relationA <-
      if(ind == "A") {
        1
      } else if (ind == "0") {
        0
      } else {
        (relationAc(pts[["P1"]]) + relationAc(pts[["P2"]])) / 2
      }
    myd[myd$Individual == ind, "relationA"] <<- relationA
    relationA
  } else {
    pts[["relationA"]]
  }
}

次に、キャッシュを初期化する必要があります。

myd$relationA <- NA_real_

1回の呼び出しで必要な値が入力され、個人のセット全体を呼び出すと、すべての値が入力されます。

> myd
   Individual P1 P2 relationA
1           A  0  0        NA
2           B  0  0        NA
3           C  A  B        NA
4           D  0  0        NA
5           E  C  D        NA
6           F  C  E        NA
7           G  0  0        NA
8          H1  E  G        NA
9          H2  E  G        NA
10         H3  E  G        NA
11         H4  E  G        NA
12         H5  E  G        NA
13         K1 H1 H1        NA
14         K2 H2 H2        NA
15         K3 H3 H3        NA
16         K4 H4 H4        NA
17         K5 H5 H5        NA
> relationAc("K5")
[1] 0.125
> myd
   Individual P1 P2 relationA
1           A  0  0     1.000
2           B  0  0     0.000
3           C  A  B     0.500
4           D  0  0     0.000
5           E  C  D     0.250
6           F  C  E        NA
7           G  0  0     0.000
8          H1  E  G        NA
9          H2  E  G        NA
10         H3  E  G        NA
11         H4  E  G        NA
12         H5  E  G     0.125
13         K1 H1 H1        NA
14         K2 H2 H2        NA
15         K3 H3 H3        NA
16         K4 H4 H4        NA
17         K5 H5 H5     0.125
> sapply(myd$Individual, relationAc)
    A     B     C     D     E     F     G    H1    H2    H3    H4    H5    K1 
1.000 0.000 0.500 0.000 0.250 0.375 0.000 0.125 0.125 0.125 0.125 0.125 0.125 
   K2    K3    K4    K5 
0.125 0.125 0.125 0.125 
> myd
   Individual P1 P2 relationA
1           A  0  0     1.000
2           B  0  0     0.000
3           C  A  B     0.500
4           D  0  0     0.000
5           E  C  D     0.250
6           F  C  E     0.375
7           G  0  0     0.000
8          H1  E  G     0.125
9          H2  E  G     0.125
10         H3  E  G     0.125
11         H4  E  G     0.125
12         H5  E  G     0.125
13         K1 H1 H1     0.125
14         K2 H2 H2     0.125
15         K3 H3 H3     0.125
16         K4 H4 H4     0.125
17         K5 H5 H5     0.125
于 2012-11-16T18:57:09.983 に答える
3

編集:

より簡潔に言えば、を使用sapplyrowSumsfor-loop、1行のコードにまとめることができます。

# Initialize values of relationA
myd$relationA <- 0
myd$relationA[myd$Individual=="A"] <- 1

# Calculate relationA
myd$relationA <-   myd$relationA + rowSums(sapply(myd$Individual, function(indiv) 
     myd$relationA[myd$Individual==indiv]/2 * ((myd$P1==indiv) + (myd$P2==indiv))))



あなたが探しているものはこのようなものですか?

# Initialize values of relationA
myd$relationA <- 0
myd$relationA[myd$Individual=="A"] <- 1


# Iterate over all Individuals
for (indiv in myd$Individual) {

  indiVal <- myd$relationA[myd$Individual==indiv]

  # all columns handled at once, thanks to vectorization;  no need for myd$P1[i]
  myd$relationA <- myd$relationA  + 
                 indiVal/2 * ((myd$P1==indiv) + (myd$P2==indiv))
}

出力

myd
   Individual P1 P2 relationA
1           A  0  0     1.000
2           B  0  0     0.000
3           C  A  B     0.500
4           D  0  0     0.000
5           E  C  D     0.250
6           F  C  E     0.375
7           G  0  0     0.000
8          H1  E  G     0.125
9          H2  E  G     0.125
...
于 2012-11-16T17:47:48.617 に答える