0

生存分析で使用するための打ち切り従属変数を開発しています。私の目標は、誰かが調査で質問に最後に答えた時間(「時間」)を見つけることです(たとえば、「q.time」が「1」としてコード化され、「q.time +1」とqがまったくない点)。以降の時間は「0」としてコード化されます。

このロジックにより、最後に回答された質問は「1」(q.time)としてコード化されます。回答されない最初の質問(q.time + 1)は、「0」としてコーディングする必要があります。また、最初の質問に答えられなかった後のすべての質問は、「NA」としてコード化する必要があります。次に、DV=NAであるすべての行をデータセットから削除します。

非常に寛大な同僚が私が次のコードを開発するのを手伝ってくれましたが、彼は今休暇中であり、もう少し愛情が必要です。コードは次のとおりです。

library(plyr)  # for ddply 
library(stats)  # for reshape(...) 
# From above 
dat <- data.frame( 
  id=c(1, 2, 3, 4), 
  q.1=c(1, 1, 0, 0), 
  q.2=c(1, 0, 1, 0), 
  dv.1=c(1, 1, 1, 1), 
  dv.2=c(1, 1, 0, 1)) 
# From above 
  long <- reshape(dat, 
                direction='long', 
                varying=c('q.1', 'q.2', 'dv.1', 'dv.2')) 
   ddply(long, .(id), function(df) { 
# figure out the dropoff time 
answered <- subset(df, q == 1) 
last.q = max(answered$time) 
subs <- subset(df, time <= last.q + 1) 
# set all the dv as desired 
new.dv <- rep(last.q,1) 
if (last.q < max(df$time)) new.dv <- c(0,last.q) 
subs$dv <- new.dv 
subs 
})

残念ながら、これによりエラーメッセージが表示されます。

"Error in `$<-.data.frame`(`*tmp*`, "dv", value = c(0, -Inf)) : 
 replacement has 2 rows, data has 0"

何か案は?問題は「rep」コマンドにあるようですが、私はRの初心者です。どうもありがとうございました。

更新:以下の説明を参照してから、フォローアップの質問を参照してください

こんにちは。私は完全にあなたをフォローしました。あなたが私を助けてくれた時間を本当に感謝しています。私は自分のデータに戻り、すべての回答者の値が「1」であるダミーのQにコーディングしましたが、エラーが実際にどこにあるのかを発見しました。私の実際のデータセットには、30の質問があります(つまり、長い形式で30回)。すべてのid変数に対してFORSUREq == 1になるようにデータセットを変更した後、エラーメッセージは次のように変わりました。

"Error in `$<-.data.frame`(`*tmp*`, "newvar", value = c(0, 29)) : replacement has 2 rows, data has 31"

問題が潜水艦に割り当てられた行数にある場合、エラーの原因は...

subs <- subset(df, time <= last.q + 1) 

つまり、$time <= last.q + 1$は、行数を値EQUALのlast.q + 1に設定していますか?

更新2:理想的には、新しい変数をどのように見せたいですか?

 id  time q  dv   
 1    1   1   1
 1    2   1   1
 1    3   1   1
 1    4   1   1
 1    5   0   0
 1    6   0   NA
 2    1   1   1
 2    2   1   1
 2    3   0   0
 2    4   0   NA
 2    5   0   NA
 2    6   0   NA

「q」は時間の経過とともに「0」または「1」の間で変化する可能性があることに注意してください(time=2でのid=1の観測を参照)が、生存分析の性質上、「dv」は変化しません。私がする必要があるのは、「q」が「1」と「0」の間で変化する最後の時間を見つけ、それに応じて打ち切られる変数を作成することです。ステップ4の後、私のデータは次のようになります。

 id  time q  dv   
 1    1   1   1
 1    2   1   1
 1    3   1   1
 1    4   1   1
 2    1   1   1
 2    2   1   1
 2    3   0   0
4

3 に答える 3

5

.(id)plyrはと同等です

> dum<-split(long,long$id)
> dum[[4]]
    id time q dv
4.1  4    1 0  1
4.2  4    2 0  1

あなたの問題はあなたの4番目の分割にあります。あなたが参照する

answered <- subset(df, q == 1)

あなたの関数で。dum[[4]]$q値1がないため、これは空のセットです。

この分割を無視したいだけなら、

ans<-ddply(long, .(id), function(df) { 
# figure out the dropoff time 
answered <- subset(df, q == 1) 
if(length(answered$q)==0){return()}
last.q = max(answered$time) 
subs <- subset(df, time <= last.q + 1) 
# set all the dv as desired 
new.dv <- rep(last.q,1) 
if (last.q < max(df$time)) new.dv <- c(0,last.q) 
subs$dv <- new.dv 
subs 
})

> ans
  id time q dv
1  1    1 1  2
2  1    2 1  2
3  2    1 1  0
4  2    2 0  1
5  3    1 0  2
6  3    2 1  2

結果になります

于 2012-07-12T02:03:02.710 に答える
5

要するに:エラーはq == 1いつがないためid == 4です。


ここで何が起こっているかを確認する良い方法は、関数を個別に書き直し、ddplyが処理している各チャンクを手動でテストすることです。

したがって、最初に次のようにコードを書き直します。

myfun <- function(df) { 
  # figure out the dropoff time 
  answered <- subset(df, q == 1) 
  last.q = max(answered$time) 
  subs <- subset(df, time <= last.q + 1) 
  # set all the dv as desired 
  new.dv <- rep(last.q,1) 
  if (last.q < max(df$time)) new.dv <- c(0,last.q) 
  subs$dv <- new.dv 
  subs
}
ddply(long, .(id), myfun )

もちろん、それでもエラーが発生しますが、少なくとも今では、ddplyが何をしているかを手動で確認できます。

ddply(long, .(id), myfun )本当に意味する:

  1. longと呼ばれるデータフレームを取る
  2. いくつかのサブセットデータフレームを作成します(個別のIDごとに1つ)
  3. 関数myfunをサブセット化された各データフレームに適用します
  4. 結果を単一のデータフレームに再構成します

それでは、ddplyが自動的に実行していることを手動で実行してみましょう。

    > myfun(subset(long, id == 1))
        id time q dv
    1.1  1    1 1  2
    1.2  1    2 1  2
    > myfun(subset(long, id == 2))
        id time q dv
    2.1  2    1 1  0
    2.2  2    2 0  1
    > myfun(subset(long, id == 3))
        id time q dv
    3.1  3    1 0  2
    3.2  3    2 1  2
    > myfun(subset(long, id == 4))
    Error in `$<-.data.frame`(`*tmp*`, "dv", value = c(0, -Inf)) : 
      replacement has 2 rows, data has 0
    In addition: Warning message:
    In max(answered$time) : no non-missing arguments to max; returning -Inf
    > 

したがって、エラーはddplyがid==4の関数を適用するステップから発生しているようです。

次に、関数の外にあるコードを取り出して、各チャンクを調べてみましょう。

> #################
> # set the problem chunk to "df" so we 
> # can examine what the function does
> # step by step
> ################
> df <- subset(long, id == 4)
> 
> ###################
> # run the bits of function separately
> ###################
> answered <- subset(df, q == 1) 
> answered
[1] id   time q    dv  
<0 rows> (or 0-length row.names)
> last.q = max(answered$time) 
Warning message:
In max(answered$time) : no non-missing arguments to max; returning -Inf
> last.q
[1] -Inf
> subs <- subset(df, time <= last.q + 1) 
> subs
[1] id   time q    dv  
<0 rows> (or 0-length row.names)
> # set all the dv as desired 
> new.dv <- rep(last.q,1) 
> new.dv
[1] -Inf
> if (last.q < max(df$time)) new.dv <- c(0,last.q)  
> subs$dv <- new.dv 
Error in `$<-.data.frame`(`*tmp*`, "dv", value = c(0, -Inf)) : 
  replacement has 2 rows, data has 0
> subs
[1] id   time q    dv  
<0 rows> (or 0-length row.names)
> 

したがって、発生するエラーはsubs$dv <- new.dv、new.dvの長さが2(つまり、2つの値-(0、-Inf))であるが、sub $ dvの長さが0であるために発生します。これは、dvが単純なベクトルの場合は問題になりません。ただし、列がすべて2行あるデータフレーム内にあるためsub、sub$dvにも2行が必要です。

sub行がゼロである理由は、 q == 1whenがないためid == 4です。

最終的なデータフレームには何も含まないべきid == 4ですか?あなたの問題への答えは、実際には、がない場合に何をしたいかによって異なりq==1ますid。お知らせいただければ、コードのサポートをさせていただきます。

アップデート:

発生しているエラーは、subs$dv31個の値があり、new.dv2個の値があるためです。

Rでは、長いベクトルを短いベクトルに割り当てようとすると、常に文句を言います。

> test <- data.frame(a=rnorm(100),b=rnorm(100))
> test$a <- rnorm(1000)
Error in `$<-.data.frame`(`*tmp*`, "a", value = c(-0.0507065994549323,  : 
  replacement has 1000 rows, data has 100
> 

ただし、短いベクトルを長いベクトルに割り当てると、短いベクトルが長いベクトルの偶数倍でない場合にのみ文句が表示されます。(たとえば、3は100に均等になりません)

> test$a <- rnorm(3)
Error in `$<-.data.frame`(`*tmp*`, "a", value = c(-0.897908251650798,  : 
  replacement has 3 rows, data has 100

しかし、これを試してみると、2が100に均等になるので文句はありません。

> test$a <- rnorm(2)
>

これを試して:

 > length(test$a)
[1] 100
> length(rnorm(2))
[1] 2
> test$a <- rnorm(2)
> length(test$a)
[1] 100
>

それがしていることは、長いベクトルを埋めるために短いベクトルを静かに繰り返すことです。

繰り返しになりますが、エラーを回避するために何をするか(つまり、両方のベクトルを同じ長さにするか)は、達成しようとしていることによって異なります。new.dv短くしますか、それともsubs$dv長くしますか?

于 2012-07-12T02:19:22.670 に答える
0

まず、クレジットが必要な場所にクレジットを与えるために、以下のコードは私のものではありません。それは、私の問題を(何時間も!)解決するのを手伝ってくれた別の非常に寛大な同僚(およびエンジニア)と共同で生成されました。

調査データから打ち切り変数を作成することを任された他のアナリストは、このコードが役立つと思うかもしれないと思ったので、私は解決策を渡します。

library(plyr)
#A function that only selects cases before the last time "q" was coded as "1"
slicedf <- function(df.orig, df=NULL) {
if (is.null(df)) {
    return(slicedf(df.orig, df.orig))
}
if (nrow(df) == 0) {
    return(df)
}
target <- tail(df, n=1)
   #print(df)
   #print('--------')
   if (target$q == 0) {
       return(slicedf(df.orig, df[1:nrow(df) - 1, ]))
   }
if (nrow(df.orig) == nrow(df)) {
    return(df.orig)
}
return(df.orig[1:(nrow(df) + 1), ])
}
#Applies function to the dataset, and codes over any "0's" before the last "1" as "1"
long <- ddply(long, .(id), function(df) {
df <- slicedf(df)
if(nrow(df) == 0) {
return(df)
}
q <- df$q
if (tail(q, n=1) == 1) {
df$q <- rep(1, length(q))
} else {
df$q <- c(rep(1, length(q) - 1), 0)
}
return(df)
})

あなたの忍耐と助けにコメントしてくれたオンラインのみんなに感謝します。

于 2012-07-12T20:12:21.773 に答える