2

R を学習する途中で、私は自分自身に少し挑戦しました。問題は、平均が 20 の正規分布の 500 個の数値のサンプルが与えられた場合、標準偏差が 6 から 10 の場合、20 未満の数値がいくつ得られるかということでした。詳細 各 sd に対して 4 つのサンプルを取得することにしました。だから最後に私が持っている必要があります:

sd6samp1:...

sd6samp2:...

....

sd10samp4:...

うまくいった私の最初のアプローチは次のとおりです。

 ddss<-c(6:10) # sd's
 sam<-c(1:4) # 4 samples for each
 k=0  # counter in 0
 for (i in ddss) {   # for each sd
   for (j in sam) {  # for each sample
     nam <- paste("sam",i,".",j, sep="") # building a name
     n <- assign(nam,rnorm(500, 20, i))  # the great assign function
     k <- k+sum(n<=0)
   }
   print(assign(paste("ds",i,sep=""), k)) # ohh assign you're great
   k=0 # reset counter
 }

ループする「i」を使用して変数名を作成する方法を探しているときに、「assign」が機能することを発見しましたが、次のようにも述べています。

ただし、いくつかのシミュレーションを計画している場合、多くの専門家はリストを使用する必要があると言うことに注意してください。

だから、リストを学ぶのはいいと思う...

その間、私は他の素晴らしいオプションも発見しました... ddss <- c(6:10)

for (i in ddss) {
   print(paste('prob. x<=0), with sd=',i))
   print(pnorm(0,mean=20,sd=i)*500)
}

これは質問に答えるのに役立ちましたが、リストはまだ作成されていませんでした...そして多くのRはまだ学習されていません。主なアイデアは、ネガの確率や数を知ることではなく、R と具体的にはいくつかのループを学ぶことでした。

だから、私は言及されたリストに行こうとしてきました

私の最も近いアプローチは次のとおりです。

ddss<-c(6:10) # sd's to be calculated.
sam<-c(1:4) # 4 samples for each sd
liss<-list()  # initializing the list
for (i in ddss) {   # for each sd
   liss[[i]] <- list()
   for (j in sam) {  # for each sample
      liss[[i]][[j]] <- rnorm(500, 20, i)
      print(paste('ds',i,'samp',j,'=',sum(liss[[i]][[j]]<0)))
   }
}

これで情報を取得できますが、2 つの問題 (1 & 2) とその他の質問 (3 & 4) について疑問に思っています。

  1. 10 個の要素のリストを取得します。6 個の空の要素と、4 個のサブリストがあります。リストの要素 1:4 (sd) を 6:9 の名前 (まさに sd) で操作する方法を見つけることができないようです。

  2. 試してみましたが、「for」ループを介してリスト要素に名前を付けることができませんでした。これらの問題に関する洞察は素晴らしいでしょう。

  3. シミュレーションのこのコンテキストで以来。ネストされたリスト (サブリストを含むリスト) と単純な (長い) リストのどちらが優れていると思いますか?

  4. ここで「適用」機能が役立つかどうか疑問に思ったので、次のようなことを試みました。

vbv<-matrix(c(6,6,6,6,7,7,7,7,8,8,8,8,9,9,9,9))
lsl<-apply(vbv, 2, function(x) rnorm(500,20,x))

でも、なかなか近寄れそうにない……。

ここまで読んでくれてありがとう!

返信にはもう少し時間がかかるかもしれません;-)。

4

3 に答える 3

4

問題はインデックスにあります。6 から 10 まで実行される ddss からインデクサー i を実行しています。したがって、外側のループでの最初の義務のツアーでは、最初のステートメントは実際には次のように述べています: liss[[6]]<-list()、最初の 5 つが NULL であることを意味します.

したがって、ループを使用することを主張する場合は、これを行う必要があります (チェックしてください?seq_along):

ddss<-c(6:10) # sd's to be calculated.
sam<-c(1:4) # 4 samples for each sd
liss<-list()  # initializing the list
for (i in seq_along(ddss)) {   # now, i runs from 1 to 5
   liss[[i]] <- list()
   for (j in sam) {  # for each sample
      liss[[i]][[j]] <- rnorm(500, 20, i)
      print(paste('ds',ddss[i],'samp',j,'=',sum(liss[[i]][[j]]<0)))
   }
   names(liss[[i]])<-as.character(sam)#this should solve your naming issue (1/2)
}
names(liss)<-as.character(ddss)#this should solve your naming issue (2/2)

いつものように、変数に i や j よりも便利な名前を付けることをお勧めします。curds という名前を付けていたら、リスト内のインデクサーとしてすぐに使用しなかったのではないでしょうか?

さて、あなたが本当に改善を目指しているのであれば (しかしリストに固執したいのであれば)、スタイル適用関数を使いたいと思うでしょう:

liss<-lapply(ddss, function(curds){ #apply the inline function to each ds and store results in a list
  return(lapply(sam, function(cursam){ #apply inline function to each sam and store results in a list
    rv<-rnorm(500, 20, curds)
    cat('ds',curds,'samp',cursam,'=',sum(rv<0), "\n") #maybe better for your purposes.
    return(rv)
  }))
}) 

最後に、あなたの場合、実際にリストを使用する理由はあまりありません (また、各 ds/sam のサンプリングされたデータを保持する必要さえありません): すべてを 3 次元配列として格納できますが、次のように指定するためです。学習課題 (ちょっと、配列のことが次の課題になるかもしれません :-))、それはそのままにしておきます。

于 2011-06-10T08:34:51.757 に答える
3

plyrこのような演習に合わせて作成されたパッケージを使用して、別のソリューションを投入します。

library(plyr)

# generate a data frame of parameters, repeating some as required
parameters  = data.frame(mean = 20, sd = rep(6:10, each = 4))

# generate sample data for each combination of parameters
sample_data = mdply(df, rnorm, n = 500)

# generate answer by counting number of observations less than 20
answer = data.frame(
    parameters, 
    obs_less_20 = rowSums(sample_data[,-c(1, 2),] < 20)
)

head(answer)

mean sd obs_less_20
1   20  6         247
2   20  6         250
3   20  6         242
4   20  6         259
5   20  7         240
6   20  7         237
于 2011-06-10T16:11:24.443 に答える
3

lapply()ここでは、SD の一連の値に適用できます。関数の周りにカスタム ラッパーを記述するrnorm()と、 のさまざまな引数に異なる値を渡してrnorm()、k 個の複製 (この例では k = 4) をうまく処理できるようなります。そのラッパーはfoo()以下のとおりです。

foo <- function(sd, n, mean, reps = 1) {
    rands <- rnorm(n * reps, mean = mean, sd = sd)
    if(reps > 1)
        rands <- matrix(rands, ncol = reps)
    rands
}

lapply()次のように呼び出しで使用します。

sims <- lapply(6:10, FUN = foo, mean = 20, n = 500, reps = 4)

これにより、次のことが得られます。

R> str(sims)
List of 5
 $ : num [1:500, 1:4] 30.3 22 15.6 20 19.4 ...
 $ : num [1:500, 1:4] 20.9 21.7 17.7 35 30 ...
 $ : num [1:500, 1:4] 17.88 26.48 5.19 19.25 15.59 ...
 $ : num [1:500, 1:4] 27.41 12.72 9.38 35.09 11.08 ...
 $ : num [1:500, 1:4] 16.2 11.6 20.5 35.4 27.3 ...

次に、SD あたり < 20 の観測数を計算できます。

names(sims) <- paste("SD", 6:10, sep = "")
out <- lapply(sims, function(x) colSums(x < 20))

これにより、次のことが得られます。

R> out
$SD6
[1] 218 251 253 227

$SD7
[1] 250 242 233 232

$SD8
[1] 258 241 246 274

$SD9
[1] 252 245 249 258

$SD10
[1] 253 259 241 242

@Joris は、リストの要素にアクセスする方法を示すことを提案しています。たとえば、SD = 20 のシミュレーションの結果が必要な場合は、out[[4]]適用した SD のベクトルの 4 番目の値が 20 であったため、または、出力 list の要素に名前を付けたため、次のoutようにすることができます。を使用したシミュレーションの結果out[["SD10"]]

ループなどに関する特定のポイントのいくつかに答えるには、

  • リストに名前を追加するにはnames()、たとえばnames(mylist)<- c("foo","bar") . You'd be better off in your loop callingnames()` をループの反復ごとに 1 回使用して、1 回のショットで名前を設定します。名前をつけていくのは非効率的です。
  • 私の例のように、ネストされたリストを使用するか、マトリックスを含むリストを使用するかは、それほど大きな違いはないと思います。foo()の出力がリストのリストになるようにリストを返すように変更するlapply()には、次のようにします。

コード:

bar <- function(sd, n, mean, reps = 1) {
    rands <- rnorm(n * reps, mean = mean, sd = sd)
    if(reps > 1)
        rands <- split(rands, rep(seq_len(reps), each = n))
    rands
}
sims2 <- lapply(6:10, FUN = bar, mean = 20, n = 500, reps = 4)
names(sims2) <- paste("SD", 6:10, sep = "")
out2 <- lapply(sims2, function(x) sapply(x, function(y) sum(y < 20)))

これにより、以前と同じ出力が得られます。

于 2011-06-10T08:30:13.917 に答える