*このページは編集中です。 [#ta52f8d0]
*Rを使ったプログラミング [#ub51ef7f]

**前回やった2項検定の補足:どうしてp値が0.04139になるか? [#ze826fec]
**&color(green){【トピックス】};帰無仮説・有意水準・有意差・仮説検定。。。が分からない [#b4099b8b]
前回授業でやった仮説検定のところがよくわからなかったという意見が多かったです。そこで、正確さは二の次にして、仮説検定で行っている作業をイメージで理解してもらえるようまとめてみました。それぞれどこの部分が、帰無仮説、有意水準、帰無仮説の棄却にあたるのか考えてみてください。また、なんとなく理解できたら、統計の教科書を読んでみることを強くお勧めします。
~
~
>
#ref(./snmpenwl.gif,left,around,nolink) 
#ref(./WS000002.JPG,right,around,nolink)
&size(16){1枚のコインを20回投げたら、オモテが5回しかでなかった。このコインはいかさまコインかなー?};
~
~
~
//#ref(./snmpendf.gif,right,around,nolink)
~&size(16){もし、このコインがいかさまコインじゃない(正常なコイン)とすると...};
~&size(16){20回中5回しかオモテが出ないのっていうのも、わりとフツーに起こることなんだろーね。};
~
~
~
#ref(./snmpensl.gif,left,around,nolink)
#ref(./pengraph.gif,right,around)
~&size(16){わりとフツーに起こるこってどうやって数字で示す?確率で 95パーセントぐらいかな?...};~
&size(16){正常なコインを20回投げた時のオモテの数ごとに、確率をグラフで表してみると...};
~
~
~
~
~
#ref(./snmpengi.gif,left,around,nolink)
&size(19){なんと!!};&size(17){95パーセント以上っていうのは、オモテの数が6枚から14枚までの場合だっ!};
~&size(17){オモテの数が5枚の場合は、5%の範囲というフツーじゃ起こらないとした範囲に含まれちゃってる...};
~
~
~
&size(16){「20回中5回しかオモテが出ない」っていうのが、「正常なコイン」ではフツーに起こらないっていうわけだから、};
~&size(16){このコインが「正常なコイン」っていう前提が間違っていたと考える方がいいんだろうね。};
~&size(16){うん、きっとこのコインは、いかさまコインなんだ};
~
~
~
#ref(./snmpenas.gif,right,around,nolink)
&size(16){でも、待てよ。フツーじゃ起こらないことの判断基準が5%って大きすぎない?};~
&size(16){5%っていうと、、、100回中5回。。。}; &size(18){20回中に1回だ!};~
&size(16){っていうことは、もしも「正常なコイン」という前提が正しくても、20回に1回は、間違った判断を下してしまう可能性があるってことだね。};



-&size(11){&color(brown){注:};今回このページで用いたペンギンのアイコンは、ホームページ用フリー素材集★沙奈の小物箱★ http://www2g.biglobe.ne.jp/~misana/ から使わせていただきました。};

#contents

**仮説検定:用語の整理: [#na4e9b31]
-帰無仮説:検定されるべき仮説。
-第一種の誤り:本当は帰無仮説は真実なのに棄却してしまうという誤り
-第二種の誤り:本当は帰無仮説は間違っているのに、受け入れてしまうという誤り
|>||>|CENTER:帰無仮説を|
|>|~|CENTER:受け入れる|CENTER:棄却する|
|帰無仮説が|真実|結論は正しい|第一種の誤り|
|~|間違い|第二種の誤り|結論は正しい|
-有意水準:帰無仮説を受け入れるか、受け入れないかの判断の基準になる確率。ふつう、5%(0.05), 1%(0.01%), 0.1%(0.01%)が使われる。
-棄却域:帰無仮説が正しいときに起こりにくい領域の確率。有意水準と同じになるようにする。
-採択域:帰無仮説が正しいときに起こりやすい領域の確率。「1 - 有意水準」

***前回やった2項検定の補足:どうしてp値が0.04139になるか? [#u111cd72]
 > binom.test(15,20)
	Exact binomial test
 data:  15 and 20 
 number of successes = 15, number of trials = 20, p-value = 0.04139
 alternative hypothesis: true probability of success is not equal to 0.5 
 95 percent confidence interval:
  0.5089541 0.9134285 
 sample estimates:
 probability of success 
                   0.75 
~&ref(./Untitled-8.gif);&ref(./Untitled-7.gif);~
&ref(./期待値.xls);

*Rを使ったプログラミング演習 [#maa24e16]
#contents

 前回の授業で使ったRという計算ソフト。けっこう、面白かったよう。コマンドを入力するのはちょと難しいけど、エクセルみたいにマウスを使って面倒な操作をしなくても、一瞬にしてグラフが描けてしまう。これなら、良いレポートを仕上げるために、何度も解析をやりなおして、グラフを描き直すっていう作業も面倒ではなさそう。。。

 Rは前回やったよりも、さらにいろんな機能がある。今回は、皆さんから希望の多かったプログラミングを、Rを使って勉強します。

*Rのおさらい [#j465be3c]
**Rのおさらい [#s77e7cca]
 前回やったRを使った計算のおさらいを、サンプルデータをつかってやってみましょう。

**サンプルデータ: 仲岡先生の実習から [#ca1098d1]
***サンプルデータ: 仲岡先生の実習から [#x27b1da4]
下のデータは仲岡先生の実習でやった、調査コドラートの面積と、出現種数です
 コドラート1    10*10    2種
 コドラート2    15*15    4種
 コドラート3    20*20    7種
 コドラート4    25*25    7種
 コドラート5    30*30    7種
 コドラート6    35*35    9種
 コドラート7    40*40    8種
 コドラート8    45*45   12種
 コドラート9   50*50   10種
 コドラート10   55*55   10種
 コドラート11   60*60   11種
 コドラート12   65*65   11種
 コドラート13   70*70   9種
 コドラート14   80*80   10種
 コドラート15  100*100  12種
 (データ提供、してくれた方に感謝!)
 Rを使ってこのデータの、面積と種数の相関関係を知りたいとき、必要なのは、コドラートの1辺の長さと種数のベクトルです。

 &size(16){今から何をするか、もうお分かりですよね?};

予想通り、K2Editorを立ち上げて、要らないところを消し、
 10   2
 15   4
 .    .
というデータに整形して、エクセルにコピペして、1列ごとのデータを scan() 関数を使ってオブジェクトに読み込みます。では、やってみましょう。(そろそろミミタコだろうから、説明は簡単に書いておきます)
***1. K2Editorでの操作 [#p44e93f7]
***1. K2Editorでの操作 [#e319a97a]
++上の囲みのデータをコピペ
++正規表現置換
 検索文字列: ^.*\* (説明:行頭から最初のアスタリスクまで)  置換文字列:<無し>(つまり削除ということ)
 検索文字列: 種           置換文字列:<無し>
 検索文字列:  + (説明:左に書かれているのは半角のスペースと半角のプラス) 置換文字列: \t (説明:タブ)
 検索文字列: ^.*\* (説明:行頭から最初のアスタリスクまで)  
 置換文字列:<無し>(つまり削除するということ)
 
 検索文字列: 種           
 置換文字列:<無し>
 
 検索文字列:  + (説明:左に書かれているのは半角のスペースと半角のプラス) 
 置換文字列: \t (説明:タブ)
++終わったら全体を選択してコピー。 エクセルを起動

***2. エクセルでの操作 [#t0e23894]
++K2Editorで整形したデータをペースト
++2列に分かれてデータが表示される
 10  2
 15  4
 .   .
++1列のデータをコピーして、Rに移動

***3. Rでの操作 [#h2054842]
***3. Rでの操作 [#x378dbb9]
++scan()関数を使って、コドラートの一辺の長さを qに、種数をyに代入
 > q=scan()
 [1]    ← ここでペースト。yについても同様
 > y=scan()
++(確認のため、それぞれ表示しておきます)
 > q
 [1]  10  15  20  25  30  35  40  45  50  55  60  65  70  80 100
 > y
 [1]  2  4  7  7  7  9  8 12 10 10 11 11  9 10 12
++欲しいのは面積なので、xにqの2乗を入れる
 x=q^2
++それぞれの常用対数を使ってグラフにプロット(対数グラフ用紙必要無し!⌣)
 > plot(log10(x), log10(y))
++回帰分析
 > result=lm(log10(y) ~ log10(x))
 > result
 Coefficients:
 (Intercept)     log10(x)  
    -0.1375       0.3250  
 ここに表示された結果は、log(y)=0.325*log10(x)-0.1375 という回帰直線の式
++回帰直線の描画
 > abline(result)
++解析のサマリー表示
 > summary(result)
 Call:
 lm(formula = log10(y) ~ log10(x))
 Residuals:
      Min        1Q    Median        3Q       Max 
 -0.211429 -0.054045  0.006334  0.053616  0.142160 
 Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
 (Intercept) -0.13750    0.15254  -0.901    0.384    
 log10(x)     0.32498    0.04713   6.896 1.09e-05 ***  ←有意水準0.1%で有意
 ---
 Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1  ←これ、有意水準
 Residual standard error: 0.09927 on 13 degrees of freedom
 Multiple R-Squared: 0.7853,	Adjusted R-squared: 0.7688 
 F-statistic: 47.55 on 1 and 13 DF,  p-value: 1.092e-05 
++相関の検定
	Pearson's product-moment correlation
 > cor.test(log10(y),log10(x))
 Pearson's product-moment correlation
 data:  log10(x) and log10(y) 
 t = 6.8957, df = 13, p-value = 1.092e-05
 alternative hypothesis: true correlation is not equal to 0 
 95 percent confidence interval:
  0.6847590 0.9618161 
 sample estimates:
      cor 
 0.886173   ← 相関係数

 この授業では、それぞれの分析の意味については説明しません。仲岡先生に聞いて下さい。(グラフ用紙で提出しなくてもいいと仰っていたような、いなかったような。。。)

*大事なこと* 上のような解析の方法、私だってRでできるとは知りませんでした。では「回帰分析行いなさい」なんて言われたら、どうするか?もしかしてRでできるかなと思ったら、
 マニュアルを読みましょう
--http://cse.naro.affrc.go.jp/takezawa/r-tips.pdf には竹澤さんという方が書かれた詳しい説明があります。私がやったことは、Adobe Acrobat Readerで開いて、検索機能を使って「回帰分析」が載っているページを調べただけです。あとは、例を見ながら、上の解析をやってみました。
&size(16){*大事なこと*};
 「こんな解析、自分でやるのは絶対無理!」と思うかもしれませんが、
  そんなことは無いです!
 上のような解析の方法、私だってRでできるとは知りませんでした。
では今回、私はどうやったのでしょう?「回帰分析行いなさい」なんて言われたら、どうすればいいのでしょうか?もしかしてRでできるかなと思ったら、
 Adobe Readerを使って、マニュアルを検索します
--http://cse.naro.affrc.go.jp/takezawa/r-tips.pdf には船尾さんという方が書かれた詳しい説明があります。私がやったことは、Adobe Acrobat Readerで開いて、検索機能を使って「回帰分析」が載っているページを調べただけです。あとは、例を見ながら、上の解析をやってみました。


*プログラミングって何? [#a076c86e]
***仮説検定:補足 [#t9da5428]
前回アンケートで、仮説検定について「帰無仮説や有意水準などが分からない。」、「Rの操作は分かったけど、その意味が分からない」という意見があります。でも、私は、今の段階では、
 全員がRを使って仮説検定の操作を行うことができただけで十分!
と考えています。生物学では収集したデータをもとに何らかの判断を下す場合、ほとんどの場合仮説検定が必要になります。これは別に系統学や生態学に限ったことではありません。最新号のNatureに載っている染色体不安定性を示すマウスの腫瘍に関する論文でもt検定が使われています。
-http://www.nature.com/nature/journal/v447/n7147/abs/nature05886_ja.html
~議論の性質やデータの性質によって仮説検定の方法は異なりますが、今回皆さんが体験した考え方と解析方法は、いずれの仮説検定にも応用できるはずです。興味を持ったらいろんな教科書を読んだり、Rのマニュアルを読んでみてください。中澤さんの書かれた、Rを使った統計解析の解説PDF(http://phi.med.gunma-u.ac.jp/statlib/stat.pdf)は、無料ですし、Rで操作を試しながら読むことができます。



*Rを使ったプログラミング演習 [#eb2d3ff6]
 さて、今回で3週目になるRという計算ソフト。コマンドを入力するのはちょと難しいけど、エクセルみたいにマウスを使って面倒な操作をしなくても、一瞬にしてグラフが描けてしまう優れものですね。これなら、良いレポートを仕上げるために、何度も解析をやりなおして、グラフを描き直すっていう作業も面倒ではなさそう。。。
 初めて使ったソフトなのに、皆さん、すでにRの操作には慣れてきているし(全員、課題ができていた)、興味も感じてくれたよう。そこで、今回は要望の多かったプログラミングをRを使って勉強します。


**プログラミングって何? [#a076c86e]
 ところで、プログラミングって何をすることでしょうか?IT用語辞典で調べてみると、、、

  載っていません

 唯一近いところでは、「プログラミング言語」というのがあります。説明文からプログラミングに関わるところを抜き出して、「プログラミング」の説明文を作ってみると、

-''プログラミング'': 人間に理解できるように英語などを元に作られたプログラミング言語を用いて、そのままではコンピュータが実行させる命令を作ること。できた命令はソースコード、プログラム、スクリプトなどの名前で呼ばれる。命令文をコンピュータに実行させるためには、コンピュータが理解可能な機械語の羅列(オブジェクトコード)に翻訳する必要がある。プログラミング言語によっては、コンパイルという翻訳作業を別にしなければならないコンパイラ型言語と、リアルタイムに翻訳作業をしてコンピュータに命令を渡すインタプリタ型言語がある。
-''プログラミング'': 人間に理解できるように英語などを元に作られたプログラミング言語を用いて、コンピュータに実行させる命令を作ること。できた命令はソースコード、プログラム、スクリプトなどの名前で呼ばれる。命令文をコンピュータに実行させるためには、コンピュータが理解可能な機械語の羅列(オブジェクトコード)に翻訳する必要がある。プログラミング言語によっては、コンパイルという翻訳作業を別にしなければならないコンパイラ型言語と、リアルタイムに翻訳作業をしてコンピュータに命令を渡すインタプリタ型言語がある。

 今日の授業でコンピュータにあれこれ命令を与えるために使うRは、計算ソフトですが、インタプリタ型のプログラミング言語ということもできます。前回インストールしたPHPも同じくインタプリタ型のプログラミング言語です。
 今日の授業でコンピュータにあれこれ命令を与えるために使うRは、計算ソフトですが、インタプリタ型のプログラミング言語ということもできます。

 つまり、プログラミングとは、簡単に言うと、「%%%言葉を使ってコンピュータが理解できる命令を作ること%%%」 です。

**コンピュータにどんな命令ができるのか? or どんな命令がしたいか? [#hb1af07f]
 「Wordを立ち上げて文章を作成し、印刷する」とか、「Excelで家計簿を管理する」とかは、市販のソフトウェアを使った作業ですが、いずれも、非常に高度で複雑な命令が、使用者からコンピュータに向かって発せられています。マウスを動かしたらポインタが動くなんていうのは、けっこう複雑な命令ですよ。でも、ほとんどの場合、一般の人がコンピュータでやりたいと思うほとんどの作業は、わざわざ「命令」なんていうものを意識する必要は無いはずです。利用者が理解しやすく・使いやすいように、専用のソフトウェアが開発され、販売されているでしょう。

 生物学の研究者でも、プログラミングなどを経験したことの無い人は大勢います。だって、今や、DNAシーケンスの決定や、整列や、系統樹作成にだって、専用のソフトウェアがあるのですから。。。それぞれのソフトウェアの使い方を覚えれば、それですむわけです。私たちも新しい解析方法が開発されるたびに、そのソフトウェアの使い方を覚えるのに苦労しています。

 でも、それだけで、本当にいいのでしょうか?良くないという点が、まず、2つ思いつきます。

 1. 自分の目的にあったソフトウェアがいつも存在するというわけではない
 2. ソフトが存在する場合、目的の数だけ、ソフトの使い方を覚えなければならない
 
 ということです。特に1番目は致命的ですね。ソフトウェアが開発されてなかったら、目的が達成できないのですから。例えば、集団遺伝学で学ぶ、遺伝的浮動の解析ソフトなんていうのは、パソコンショップに行っても売ってないです(でも、じつは、このくらいメジャーなものなら、ネットで探せばフリーのものがあります)。

 そこで、この授業でプログラミングを勉強する理由は次の3点です。
+市販のソフトではカバーできないような目的を、コンピュータに命令を与えることで達成する
--あなたのコンピュータは実は、すごい性能をもっています。その性能はできる限りつかわないと損
+プログラミングを行うことで、目的とする生物学的現象の理解が深まる
--コンピュータは石頭なので、物事を本当に論理立てて説明してやらないと、命令を聞いてくれません
&br;
  プログラミングの過程で、生物学的現象の意味を論理立てて考える必要に迫られます
+プログラミングを行って、命令を実行させることで、初めて、コンピュータに''作業をさせている''ことが実感できる
--ワープロや表計算とかは、どちらかというと、道具を使って作業をさせられている感が強いですよね

**初めて(?)のプログラミング:"Hello World!" [#t6d4bdf7]
「Hello World!」だなんて、なんか変なタイトルだなーと思いますよね。誰が使い始めたのかは知りませんが、様々なプログラミング言語の教科書で、最初に出てくるのがこのプログラミングです(プログラムを勉強したことのある人なら、たいてい誰でも知っています)。では、早速やってみましょう。Rを立ち上げて、次のように入力してください。

 print("Hello World!")

*Rを使ったシミュレーション:集団遺伝学的解析を試してみよう! [#if40831d]
#ref(授業/H18/情報処理/10/drift.gif,around,right,80%)
 そこで、Rを使ってプログラミングを行うのですが、まず、目的が必要です。たぶん、皆さんが知っている生物学的現象で、Rをつかってやってみる一番ビジュアル的に面白いのは、集団遺伝学におけるいろんなシミュレーションでしょう。 (ただ、Rを使うデメリットは、計算速度が遅いことです。大規模なシミュレーションをやるには、インタプリタ型のソフトではつらいでしょう。)
うまくご挨拶できましたか?

 シミュレーション(simulation, 「シュミレーションでは無いですよ!」)は、数学モデルなどを用いて現実に似た状況をコンピュータ上で再現することです。模擬実験とも呼ばれています。
ここでやったのは、print()という関数を使って"Hello World!"と画面に表示させただけですが、これも
 画面にHello Worldと表示させる
ということを目的としたプログラミングです。
 えっ?それなら、Rの最初でやったオブジェクトの内容を画面に出すのもプログラミング?
と聞かれるかもしれませんが、その通りです。次の囲みの中を全てコピーして、Rのコンソールにペーストしてみましょう。
 x=c(1,2,3,4,5,6,7,8,9,10)
 sum(x)
上でやったプログラミングは、
 画面に1から10までの整数の合計を表示させる
というプログラミングです。皆さんがこれまでにやってきたRを使った操作も、何らかの処理の結果を画面に表示させるプログラミングだったわけです。なんとなく、プログラミングが身近になったでしょ?

 きっと、右の図は見たことがあるでしょう?これは、遺伝的浮動の効果を説明するときによく使われるグラフです。このシミュレーションでは、集団サイズN=100, 2つの対立遺伝子のうち、片方の対立遺伝子の頻度を示す。最初の世代の対立遺伝子の数は50:50。このグラフを使って、遺伝的浮動とはどういうものか、説明できる人はいますか?また、このグラフはどうやって作ったものですか?
**複数行の命令文 [#nc62591a]
上でやった2つのプログラミングですが、違いがありますね。"Hello World!"の方は1行だけの命令だし、合計値の方は2行になっています。プログラムは通常、いろんな処理を組み合わせて作るので、複数行になることが多いです。次に3行からなるプログラミングをやってみましょう。
 q=c(10,15,20,25,30,35,40,45,50,55,60,65,70,80,100)
 y=c(2,3,4,5,6,7,8,9,10,11,10,11,9,10,12)
 plot(log10(q^2), log10(y))

 あてます
このプログラムは、
 2つの数値ベクトルについて計算を行って、対数グラフを描く
というものでした。さっき、上でやったのと同じことを、複数行にまとめて書いて、まとめてRに命令したわけです。

 今日の授業では、Rを使って、「繰り返し」と「条件分岐」による最も単純なプログラムを、どんどん成長させていって、最終的には、上のグラフのようなものが作れるところまでを学びます。この過程で、遺伝的浮動とか、突然変異率とか、固定までの待ち時間とか、綿野さんの授業で勉強したようなことが、でてきて、たぶん、理解が深まると思います。

**Rの説明書 [#b6e9b891]
 授業では一つ一つ解説しますが、復習課題をやるときとか、自分で新たな解析に挑戦するときは、説明書が必要になるでしょう。
-http://cse.naro.affrc.go.jp/takezawa/r-tips.pdf には竹澤さんという方が書かれた、日本語のRの解説があります。知りたい内容は、pdfを開いて、Acrobat Readerの検索機能でサーチし下さい。
**Rで使う命令 [#qd8fba27]
 授業では一つ一つ解説しますが、復習課題をやるときとか、自分で新たな解析に挑戦するときは、どういう命令があるかが書かれた説明書が必要になるでしょう。
-http://cse.naro.affrc.go.jp/takezawa/r-tips.pdf には船尾さんという方が書かれた、日本語のRの解説があります。知りたい内容は、pdfを開いて、Acrobat Readerの検索機能でサーチし下さい。
また、Rを使っている最中は
 > ?plot
 > example(plot)
という風に、?の後に関数名を打てば、説明や使用例が英語で表示されます。説明文の一番最後にはExample(使用例)が載っていますので、けっこう参考になります。


**プログラミングの基礎: 繰り返しと条件分岐 [#bd49f99e]
 前回授業の課題で、プログラミングの基本は繰り返しと条件分岐だという話しをしました。
***繰り返し [#l4531379]
繰り返しは次のように for() を使って表現します。
**プログラミングの基礎: 繰り返しと代入と条件分岐 [#debe9e4c]
上で複数の行で様々な命令を一度にRに与えられるということを解説しました。でもやったことは、それぞれ個々の計算を順番に並べて、一度にペーストしただけですよね。そこで、次にもっと%%%プログラムらしい命令%%%をRに与えてみましょう。それは、''繰り返し''と''代入''と''条件分岐''というもので、プログラミングの基本中の基本です。


**繰り返し [#y178900a]
人が不得意でコンピュータが得意なことの一つは、単純な繰り返し作業を際限なく(文句も言わずに)行うことです。要するに、プログラミングの一つの目的は、そういう面倒な繰り返し計算をコンピュータにやらせることです。では、何回繰り返すかというのをどうやってコンピュータに指示するかというと、''for''という命令を使います。
-繰り返しは次のように for() を使って表現します。
 for(i in 1:10) { print(i) }
この命令は、
-iを1から10まで変化させなさい。そして、それぞれのiの値の時に、{ } で囲まれた部分の命令を実行しなさい
-{ } の中の意味は、iの値を画面にプリントしなさい
 { } で囲まれた部分の命令を10回繰り返しなさい
というものです。
 { } の中は何をする命令か分かりますか?
では、やってみましょう。1から10までの整数が表示されましたね。ここでもう一度命令文をよく見てみましょう。
 for と (i in 1:10) と { print(i) } に分かれています
   for は これから繰り返し命令が始まるよということを示しています
   (i in 1:10) は 繰り返しの回数が10回であることを示しています
          つまり、50回繰り返したかったら (i in 1:50) とします
                    iという文字の代わりに、jでも、kaisuでも、構いません
   { print(i) } は iという変数の値を画面に表示させなさいという意味です
というものです。 { }  のところは複数行に分かれていてもよく
 for(i in 1:10) {
   print(i)
 }
と書いても結果は同じです。

-縦に長くプリントされるのは格好悪いので、オブジェクトにベクトルとして代入してから表示させてみましょう。
 a=c()          #最初にNULLベクトルという空のベクトルを一つ作っておきます。
 for(i in 1:10) {
   a=append(a,i)  #aにiの値をベクトル要素として追加します。
 練習問題: 2から18までの偶数を全て表示させるプログラムをfor命令を使って作りなさい
--プログラムのことをスクリプトとも言います。Rのファイルメニューから「新しいスクリプト」を選ぶと、「スクリプトエディター」というエディターが開きます。ここで、スクリプトを書いてから、選択して右クリックすると、選択中の命令(コードとも呼ばれます)を実行できます。
 解答例:(穴埋め形式)
 for(i in _:_){   # _ のところには数字が入ります
   print(i*_)
 }
 print(a)       #最後に結果の内容を表示します

-for文を入れ子にすると、指数関数的に繰り返しの数が増えます

**代入 [#o9dd7e55]
上の  for(i in 1:10) { print(i) } というプログラムでは、iの値は繰り返しの度に違う値になります。
 1回目  iの値は1
 2回目 iの値は2
 3回目 iの値は3
 ....   ........
 10回目 iの値は10
では、一つ前の繰り返しの時のiの値を使いたい場合はどうすれば良いでしょうか?例えば、1から10までの合計をfor命令を使ってプログラミングすることを考えると、
 今の繰り返し回数のiの値に1つ前回数までの合計を加えて表示させたい
 1回目  iの値は1   1つ前までの合計は0  1 を表示
 2回目 iの値は2   1つ前までの合計は1  3 を表示
 3回目 iの値は3   1つ前までの合計は3  6 を表示
 ....   ........
 10回目 iの値は10  1つ前までの合計は45 55 を表示
こういう場合に代入という命令を使います。その命令は
 =
です。通常の計算では'='というのは「3+5=」というように、計算を行わせる意味で用いられますが、プログラミングにおいては、
 左辺の変数に右辺の計算結果を代入する
という意味で用いられます。上の計算のプログラムは次のようになります。
 goukei=0           #goukeiという変数に初期値0を代入
 for(i in 1:10) {   #以下を10回繰り返す
   goukei=goukei+i  #goukeiに前回までのgoukeiの値にiの値を足したもの代入
   print(goukei)    #goukeiの内容を画面に表示
 } 
''goukei=goukei+i''という命令文では、%%%右辺の「goukei+i」を先に計算%%%して左辺の「goukei」に代入しているところが、分かりにくいかもしれません。
 練習問題: 1から10までの数字を1つずつ順々にかけ合わせたた結果を全て表示させるプログラムを作りなさい
             1x1=1, 1x2=2, 2x3=6, 6x4=24, 24x5=...... と計算してゆくということ
--初期値というのも耳慣れない言葉かもしれません。プログラムに登場する変数は、最初の値が何かをはっきりコンピュータに教えてやらないと、メモリに残っている数値がそのまま使われてしまうことがあります。~
以下、穴埋め形式でヒントを書いておきます。_の部分(1文字とは限らない)を補ってプログラムを作成してください
 seki=_           #sekiという変数に初期値1を代入(かけ算だから)
 for(i in 1:10) {   #以下を10回繰り返す
   _=_*_  #sekiに前回までのsekiの値にiの値を掛けたもの代入
   print(seki)    #sekiの内容を画面に表示
 } 


-縦に長くプリントされるのは格好悪いので、毎回の計算結果をオブジェクトにベクトルとして代入してから表示させてみましょう。ベクトルに要素を追加するには''append''という命令を使います。
 seki=1          #sekiという変数に初期値1を代入
 kekka=c()         #kekkaというオブジェクトに空ベクトルを初期値として代入
 for(i in 1:10) {   #以下を10回繰り返す
   seki=seki*i  #sekiに前回までのsekiの値にiの値を掛けたもの代入
   kekka=append(kekka,seki)   #kekkaというベクトルにsekiの値を要素として追加
 } 
 print(kekka)      #kekkaの内容を画面に表示
''kekka=append(kekka,seki)''と''goukei=goukei+i''という2つの式はよく似た働きをしています。
 kekka=append(kekka,seki)  kekkaにsekiを要素として追加したものをkekkaに代入
 goukei=goukei+i           goukeiにiを加えたものをgoukeiに代入

-せっかくRを使ってプログラミングをしているので、結果をグラフに表示させてみましょう。上のprint(kekka)の部分を、plot(kekka)(あるいは、plot(log(kekka)))に変えるだけで、グラフとして出力することができます。値も表示させ対場合は、両方の命令を書いておけばいいです。
 seki=1          #sekiという変数に初期値0を代入
 kekka=c()         #kekkaというオブジェクトに空ベクトルを初期値として代入
 for(i in 1:10) {   #以下を10回繰り返す
   seki=seki*i  #sekiに前回までのsekiの値にiの値を掛けたもの代入
   kekka=append(kekka,seki)   #kekkaというベクトルにsekiの値を要素として追加
 } 
 print(kekka)      #kekkaの内容を画面に表示
 plot(log10(kekka))  #kekkaの対数をグラフにプロット
&size(16){ずいぶんとプログラムらしくなってきました};

-for文は2重にして使うこともできます。こういう方法で、2つの変数の総当たり計算が可能になります。
 #**次のプログラムの実行結果を予測してください。**
 for(j in 1:10) {
  for(i in 1:10){
     print(i*j)
 for(i in 1:9) {   #iの値を1から9まで1ずつ変化させる
  for(j in 1:9){   #jの値を1から9まで1ずつ変化させる
     print(i*j)    #iとjを掛けたものを表示する
  }
 }

-予想通りでしたか? 縦に長く表示されるのも格好が悪いので、今日の課題で使う関数を一つかって、行列形式で出力してみましょう
 #**次のプログラムの実行結果を予測してください。**
 result=c()
 for(j in 1:9) {
  for(i in 1:9){
    result=append(result, i*j)
-予想通りでしたか?小学生のころ呪文のように何度も唱えましたよね。上のままでは縦に長く表示されて格好が悪いので、matrixという関数をつかって、行列形式で出力してみましょう 
 #演習:九九の表をmatrixという関数を使って表示させます。_を埋めなさい
 result=c()                       #resultに空ベクトルを初期値として代入
 for(i in 1:9) {                  #iの値を1から9まで1ずつ変化させる
  for(j in 1:9){                  #jの値を1から9まで1ずつ変化させる
     result=append(_, _)          #iとjを掛けたものをresultの要素として追加
  }
 }
 matrix(result, nrow=i, ncol=j)  #nrowとncolはそれぞれ行の数、列の数を示します。
 matrix(result, nrow=i, ncol=j)   #nrowとncolはそれぞれ行の数、列の数を示す
                           #iとjはそれぞれ9で終わっているので、9x9のマスになる

-小学校のとき散々お世話になって表がでてきましたか?
-ここでresultの中身を確認して、行列表示と比較しておきましょう
 > result
-2つの結果を比較してみると分かるように、matrix()という関数は、resultに入っているベクトルを、nrowとncolの数に従って、行列に変換したものです。

***条件分岐 [#r32ace1b]
条件分岐はif()を使って表現します
 i=3
 if(i==3){print("san")}
この例では、
-iに3を代入し
-もしiが3なら "san" とプリントしなさい
という命令です。{}の中は複数行にわかれていてもよく、また、else を使えば、それ以外の条件を指定できます
 i=4
 if(i==3){
   print("san")
 } else {
   print("san deha nai")
 }
***繰り返しと条件分岐 [#a28dddc9]
 では、上の繰り返しと条件分岐を組み合わせて見ましょう
 1から10までのうち、5以外を画面に表示しなさい
というプログラムなら
 for(i in 1:10){
   if(i != 5) {    #  !=  は「等しくない」ということを示します
      print(i)
   }
 }
**条件分岐 [#x51d2950]
プログラミングの基本技の最後は1つは条件分岐です。if()を使って表現します
 i=3                     #iに3という数値を代入
 if(i==3){print("三")}  #iの値が3ならば画面に三と表示

**初めてのプログラミング:繰り返しと条件分岐を使って [#ob71bc71]
では、次のプログラムを作ってみてください
 1から10までの数字を表示させなさい、5だけは"five"と英単語で表示させなさい
この例の2つめのif命令で、iの値を評価しています。評価に使われるのは比較演算子というもので、
 ==     等しければ
 !=      等しく無ければ
 >, >=   左辺が右辺よりも大きければ、左辺が右辺以上ならば
 <, <=   左辺が右辺よりも小さければ、左辺が右辺以下ならば
ということを意味しています
--r-tips.pdfで比較演算子を検索してみよう!
 比較演算子に対して、代入の時に使った = は代入演算子といいます。
上のif命令では、次のような条件分岐が行われています。
 if(i==3){print("三")}
  ・もしiの値が3ならば、画面に三を表示。
  ・もしiの値が3で無いならば、何もしない
2番目の何もしないというのは省略されていました。

**0. シミュレーションの前段階:モデルの想定 [#g314d5f0]
 これからシミュレーションを行うのですが、つぎのような状況を想定してみましょう。
#ref(授業/H18/情報処理/10/mona2.gif,around,right)
#ref(授業/H18/情報処理/10/mona1.gif,around,right)

まず、対象とする架空の生物(仮に、「モナー」と呼びます&size(11){(注:モナーについて詳しく知りたい人は、ウィキペディアで「モナー」を検索してみてください。)};)は2倍体の生物で、雌雄の区別が無く、繁殖期になると集団内の個体が一斉に配偶子を数千億個ずつ放出して死亡します。配偶子は生息域の空間内をランダムに漂った後、24時間後に、最も近くにある配偶子と接合し、新しい繁殖個体になります。集団の生息域は空間的に限られているため、親世代と同数の子供個体しか、成熟個体になれません。どの子供が成熟個体になるかは、ランダムに決まるものとします。つまり、このモデルだと、世代間で集団サイズに変動は無いということです。モナーにはトンガリ耳と丸耳の2タイプが1対立遺伝子(A, a)で決まることが知られています。トンガリ耳の遺伝子型は(AA, Aa)、丸耳の遺伝子型は(aa)です。

&size(11){なお、上のモナーの説明は、私が今回のシミュレーションのために、適当に設定したものです。だって、''「任意交配をする有限サイズの生物集団から遺伝子をランダム抽出して、同サイズの次世代集団を作った」''なんて言い方をするよりは、生物を扱ってる感じがするでしょ?};

**1. 初めてのシミュレーション:10個体からなる集団における、遺伝子頻度変化のシミュレーション [#zeb9f52b]
 モナー10個体からなる、1つの集団を考えてみましょう。いまこの集団で、対立遺伝子Aの頻度が0.5, 対立遺伝子aの頻度が0.5のとき(10個体だから遺伝子の総数は、20個です。そのうち半分の10個がAで、10個がaです)。集団中の配偶子の接合はランダムに起こると仮定して、100世代の間に、集団中の対立遺伝子の頻度はどのように変化するでしょうか?

&ref(授業/H18/情報処理/10/slide5.gif,30%); &ref(授業/H18/情報処理/10/slide6.gif,40%);

 今から実験をするのですから、前もって予想しておいた方が面白そうです
 この集団の遺伝子頻度が1か0に固定するまでに、何世代ぐらいかかると思いますか?

 a=c(10)            #対立遺伝子aの集団中の個数
 for(i in 1:30){       #この行から対応する}までの間を 100世代分繰り返す
  counta=0          #次世代にランダムに残るaの値を入れる変数を初期化
  for(j in 1:20){      #数千億からなる配偶子プールから1個の配偶子を取り出す試行を20回行う
  if ( runif(1) < ??? ){  # *** 取り出した遺伝子がaだったならば ***
   counta=counta+1     # *** aの個数を入れる変数の値を1増やす ***
  }
  }
  out=counta/20)       #何世代目かという数字(i)と対立遺伝子aの頻度(a/20)をoutというオブジェクトに入れる
  print(out)         #outの内容を画面に表示する
  a=counta          # aの値を新しい世代の対立遺伝子aの個数(counta)で置き換える
-上では何も書かなかった、i=3では無い場合にも何かの処理をさせたい場合は、else を使います。また、表示を見やすくするために、{}の中は複数行にわかれていても構いません
 i=4                       #iに4を代入
 if(i==3){                 #iの値が3ならば
   print("san")            #   san と表示する
 } else {                  #iの値が3では無ければ
   print("san deha nai")   #   san deha nai と表示する
 }


上から順番に意味を考えてゆきましょう。

&ref(授業/H18/情報処理/10/slide1.gif,40%); &ref(授業/H18/情報処理/10/slide2.gif,40%);
&ref(授業/H18/情報処理/10/slide3.gif,40%);&ref(授業/H18/情報処理/10/slide4.gif,40%);

それでは、次のプログラムを走らせて、20個の遺伝子中対立遺伝子aが10個ある任意交配集団の、100世代の間のaの遺伝子頻度の変化をみてみましょう。

 a=10                        #対立遺伝子aの集団中の個数
 for(i in 1:100){             #この行から対応する}までの間を 100世代分繰り返す
  counta=0                   #次世代にランダムに残るaの値を入れる変数を初期化
  for(j in 1:20){            #数千億からなる配偶子プールから1個の配偶子を取り出す試行を20回行う
   if ( runif(1) < a/20  ){  #乱数を一つ発生させ、それが対立遺伝子aの頻度(a/20)よりも小さければ
    counta=counta+1          #aの個数を入れるcountaという変数の値を1つ増やす
***繰り返しと条件分岐 [#lc90bc80]
 では、上の繰り返しと条件分岐を組み合わせて見ましょう
 練習問題:for命令を使って1から10までの数字を表示させなさい、5だけは"five"と英単語で表示させなさい
--ヒントを穴埋め式で示しておきます。
 for(i in _:_){    #  10回繰り返し。iは1から10まで変化
   if(i == _) {    #iが5の場合
      print("five")       #fiveと表示
   } _ {       #それ以外の場合
      print(_)       #iの値を表示
   }
  }
  out=c(i, counta/20)              #何世代目かという数字(i)と対立遺伝子aの頻度(a/20)をoutというオブジェクトに入れる
  print(out)                 #outの内容を画面に表示する
  a=counta                   # aの値を新しい世代の対立遺伝子aの個数(counta)で置き換える
 }


 さて、皆さんの計算結果はどうでしたか?何世代目で固定された?


**講義についての連絡: [#n4cdcdd4]
※私が行う講義はあと4回です。7月20には、をPower Pointを使って班ごとにプロジェクトの成果を発表してもらいます。また、7月20日の残りの時間は、皆さんからの要望に応えて、もう一度解説して欲しい事項などを説明します。7月13日のアンケートで、希望をとりますので、優先順位を考えておいてください。

*第10回授業の課題 [#ic6d1e37]
全ての課題は、&size(16){http://bean.bio.chiba-u.jp/joho18/ に、「自分のID/10」という新しいページを作成し、これまでの提出例にならって、分かりやすく書き込むこと。あまりに分かりにくい回答は減点します。};
-提出期限:6月28日水曜正午(下記課題全て)
*第10回授業の課題 [#f6812b8a]
-提出期限:6月27日水曜正午(下記課題全て)
--提出期限を過ぎたものでも、点数を半分にするなどで評価しています。
**課題1.アンケート調査 [#he4f485a]
+&size(16){http://bean.bio.chiba-u.jp/joho19/ に、「自分のID」/10 という新しいページを作成し、下の囲みの中にあるアンケートをコピー・ペーストして、「回答:」の後に答えを書き込むこと。};
-手順
++個人ページのトップページ(上の方のページタイトルに、「joho19/自分のID」のみが書かれているページ)、画面の上の方にある〔 新規 〕をクリック
++ページ名を尋ねる入力スペースが表示されるので、半角英数字で、ドット・スラッシュ・1・0を下のように入力
 ./10
---注:課題提出ページが正しく作れていない場合、課題の点数から1点減点です
 良くある間違い: joho19/07s9999/06 というページを作るべきなのに joho19/07s9999/05/06 としてしまったとか

**課題1.意見調査 [#u259e7fa]
 下の囲みの中にあるアンケートをコピー・ペーストして、「回答:」の後に答えを書き込むこと。

 *第10回授業アンケート
 **氏名:
 **課題への回答
 -今日(6月22日)の授業の進み方は?(はやい、丁度いい、おそい)
 --回答:
 -今日の授業の難しさはどう感じましたか(簡単すぎ 簡単 丁度いい 難しい 難しすぎ):
 --回答:
 -難しいと答えた人は、特にどの点が難しかったですか?:
 --回答:
 -今日の授業は(よく分かった 分かった 分からなかった):
 --回答:
 -分からないと答えた人は、特にどの点が分からなかったですか?:
 --回答:
 -今日の講義で理解できなかった用語があったら挙げてください:
 --回答:
 -Rで何ができるのか、だんだん分かってきたと思います。今後自分の勉強にRを使うつもりですか?
 -Rで何ができるのか、だんだん分かってきたと思います。今後自分の勉強にRを使いたいですか?
 --回答:
 -Rでも、R以外の言語でも、何かやってみたいプログラミングはありますか?
 --回答:
 -今回やったプログラミングはおもしろかったですか?
 --回答:

**復習課題:Rによるプログラミング:繰り返しと条件分岐 [#yaa55602]

次の問題文の指定にあるプログラムを作成しなさい。作成したプログラムは課題提出ページに貼り付けなさい。
行頭には必ず半角の空白を入れること。
+  1から20までの総和を計算するプログラム(?のこと)(注:繰り返し文(for())を使ってプログラムを書いてください。sum()関数は使わないこと)
+ 乱数を20個発生させて、%%%0.5未満のものだけ%%%を画面に表示させるプログラム


-評価:
--細かい指定はしないので、プログラムをどれだけ修飾してもらってもいいです
--この問題は7点で評価します
--繰り返し、条件分岐など、プログラミングについて理解できているかどうか
--Rを用いてプログラムを正しく実行できているかどうか
--プログラムの実行内容を理解できているかどうか

**予習課題:HTMLとウェブ&プログラミング [#t8686d3c]
以下の設問に答えなさい
-問1:あなたが普段みているウェブページの本体はテキストファイルです。でも、ウェブページの画面には写真などが表示されています。文字情報だけのはずのテキストファイルで写真が表示できるのはどうしてでしょうか?
--a. ウェブページは写真をファイル内に保存できる、特殊な形式のテキストファイルである。
--b. ウェブブラウザがテキストファイルの指定に従って、別の場所に保存された写真を画面上に表示している
--c. ウェブサーバというものがテキストファイルと写真の入った画像ファイルを合成して発信している
-問2:皆さんの課題の採点結果閲覧ページは、PostgreSQLというデータベースシステムと、PHPというプログラミング言語が使われています。自分の成績ページを表示させるときに、どのような事が起きているでしょうか?
--a. インターネットにアクセスしているコンピュータに暗号化された全員分のデータがダウンロードされ、ブラウザの持っている機能で自分のデータだけ解読され、表示されている。
--b. アクセス先のウェブサーバーがデータベースサーバーからあなたのデータを取り出し、1回1回、あなた専用のウェブページを作成している。
--c. 教員が毎回、課題の採点後に、全員分の返却用ページを作成し、ウェブサーバーにアップロードしている。アカウントとパスワードを入力すると、成績データのページが納められたディレクトリに入った自分専用のページが表示される。
-問3:あなたが普段見ているウェブページは、HTMLという書式で作られており、タグと呼ばれるマークで、下線や太字を指定したり、他のページへのリンクを指定したりできます。HTML書類の中で、次のようなタグで指定された部分がありました。この部分は、ブラウザではどのように表示されるでしょうか?
 <font size="16"><i><b>HTMLの世界にようこそ!</b></i></font>
-評価:
--この問題は短いので3点で評価します
--HTMLについて自分で調べて予習したかどうか
--どの処理がサーバー側で行われ、どの処理がローカル(自分が操作しているコンピュータ)で行われているかを理解しているかどうか

------
*Rを使ったプログラミング演習(2) [#p1b85cff]
 **素朴な疑問**
 「こういうシミュレーションのプログラミングって、これから生物学を学ぶのに、どのくらい必要なんですか?」
 ==おへんじ=
 画一的な答えは難しいです。シミュレーションそのものが直接必要になるような分野もあれば、そうでない分野もあります。
 ただ、私は、プログラミングは、生物学における発展的な情報処理をする上での基本技だと考えています。
 千葉大の研究室に限って言えば、プログラミング技術が無いと卒業研究が終わらないというところは
 現時点では(たぶん)無いでしょう。但し、プログラミングができると、卒業研究や修士の研究でより
 進んだことができたり、理解が深まったり、研究が楽になるようなところはいくつもあります。
 数理生物学、理論集団遺伝学、進化生態学、バイオインフォマティクスを志す人には、
 敢えて、不可欠な技術だと言っておきます。

-&color(,"#eef"){&size(12){でもね、実は授業でこれを取り上げる理由は、「こんなことができる」と「体験」してもらうことです。こういう考え方や技術を今のうちに知っておけば、もしかしたら、皆さんの中から、素晴らしい解析プログラムを作っちゃう人が現れるかも知れませんからね。};};

*前回のおさらい [#id79d5cb]
それでは、次のプログラムを走らせて、20個の遺伝子中対立遺伝子aが10個ある任意交配集団の、100世代の間のaの遺伝子頻度の変化をみてみましょう。

 numa=10                        #対立遺伝子aの集団中の個数
 for(i in 1:100){             #この行から対応する}までの間を 100世代分繰り返す
  counta=0                   #次世代にランダムに残るaの値を入れる変数を初期化
    for(j in 1:20){            #数千億からなる配偶子プールから1個の配偶子を取り出す試行を20回行う
      if ( runif(1) < numa/20  ){  #乱数を一つ発生させ、それが対立遺伝子aの頻度(a/20)よりも小さければ
        counta=counta+1          #aの個数を入れるcountaという変数の値を1つ増やす
      }
    }
  out=c(i, counta/20)              #何世代目かという数字(i)と対立遺伝子aの頻度(a/20)をoutというオブジェクトに入れる
  print(out)                 #outの内容を画面に表示する
  numa=counta                   # aの値を新しい世代の対立遺伝子aの個数(counta)で置き換える
 }


 前回、全角の空白が混じっていたため、うまく動かなかったプログラムがこれです。まず、これを始めに動かしてみて、
 もう一度、プログラムの内容を理解してゆきましょう。

**遺伝的浮動のプログラムをステップ・バイ・ステップで理解する [#s1b6e76c]
-&ref(slide5.gif,around,right,40%);

前回のレポートで、コピー・ペーストすれば動くのはわかるけど、どうやったらこういうのが作れるのか分からないという意見がありました。私としては、クラスのほとんどの人に、プログラミングとはどういうことをするものかを分かって欲しいので、作成過程を1つずつ、順を追って説明します。
+まず、前回説明した「モナーの生活環」をみて、シミュレーションの条件を自分で考える。最初のシミュレーションなので、簡単に、
 20個の遺伝子からなる集団
 0世代目の対立遺伝子aの数が10(つまり対立遺伝子aの頻度は0.5)
 この集団を100世代観察する
という条件にしておく
+今、上に書いた数字に自分で考えた変数名をつける。名前を付けておくと、あとでコンピュータに命令すときに便利だから。数値が決まっているものは代入しておく。名前は、Rの内部で使われているもの以外なら、何でも良い。自分に分かりやすいようにつける。
 *自分で考えた変数名と定数
 numa=10   #0世代目の対立遺伝子aの数。2世代目以降は、シミュレーション実験で抽出されたaの数が代入される
 counta=0    #配偶子プールから、次世代の集団に取り出された対立遺伝子aの数。1世代が終わったあとで、
              数字が入るので、とりあえず今は0を入れておく
 20  #集団の大きさ(つまり、集団に含まれる遺伝子の数)
 100  #繰り返しの世代数
&ref(授業/H18/情報処理/11/slide10-1.gif,40%);
&ref(授業/H18/情報処理/11/slide10-2.gif,40%);
+変数名が決まったら、プログラムの構造を考える。紙に絵をかいて、どういうプログラムなら、「モナー」の生活環を模倣できるか考えたら(ここはホワイトボードにお絵かき)、言葉にしてみる。
 *自分で考えたプログラムの構造。コマンドを使って書かなくても、
   とりあえず、構造が理解できるように書いてあればよい。
&ref(授業/H18/情報処理/11/slide10-3.gif,40%);
++何世代分か、以下の操作を繰り返す
++ 1つの世代の中では、配偶子プールから配偶子を1つ選ぶという操作を20回(遺伝子の数)繰り返す
++   取り出した配偶子が対立遺伝子aだったら、変数countaの値を一つ増やす。そうでなかったら何もしない
++ 集団内で、20回配偶子を取り出す繰り返しが終わったら、対立遺伝子aの数を numaに代入する
++次世代の集団における対立遺伝子aの頻度(num/20)をプリントする
+プログラムの構造ができたのだから、次ぎに、一つ一つのステップを、コンピュータが理解できる文で表現してみる。
++まず、100世代この集団を観察するのだから、繰り返し文で100回繰り返す構造が必要になる。
 *100回繰り返す繰り返し文の構造
 for(i in 0:100) {
       <※ここに繰り返される内容が入る>
 }
++1世代で行われる操作(上の※の部分)は、1つの集団から配偶子を親の集団と同数(つまり、20個)取り出すという繰り返し操作。なので、上の100回繰り返すfor文の中には、さらに、集団中の遺伝子の数だけ繰り返すfor文が入る
 ※集団中の遺伝子数分、つまり、20回繰り返す文
    for(j in 0:20) {
      <※※ここに繰り返される内容が入る>
    }
++上のfor文の中では、配偶子プールからpopsize個取り出した配偶子の中に、対立遺伝子aがいくつ含まれているかを数えること。そのとき、
  ※※の操作:
   「配偶子を一つ取り出すとき、遺伝子頻度の確率で、対立遺伝子aをひく。もし、対立遺伝子aを引いたら、
     aの数を入れておく変数(counta)の値を1つ増やす」
  &size(24){=};  &ref(授業/H18/情報処理/11/slide10-4.gif,40%);   &ref(授業/H18/情報処理/11/slide10-5.gif,40%);
   上の『対立遺伝子aを引いたら』(このことは対立遺伝子頻度aの確率で生じる)というのは、
    『乱数を一つ発生させたとき、それが対立遺伝子頻度aより低かったら』(これも対立遺伝子頻度aの確率で生じる)と
   同じことと考える。そこで、
  「乱数を一つ発生させたとき、それが対立遺伝子頻度aより低かったら、
     aの数を入れておく変数(counta)の値を1つ増やす」
---ここが理解されなかったら、Rを使ってrunif(20)を表示させる。0.5より小さい値の数を数えて、次世代の集団の対立遺伝子aの頻度とし、もう一度Rを使って乱数発生。この操作を3回ぐらいやる
++上の操作を、20回繰り返したら、countaという変数には、取り出された対立遺伝子aの数(countaという名前にしてある)が入っているはず。この値は、次世代の集団における対立遺伝子aの数なので、次世代(つまり、外側のfor文の次の繰り返し)に渡さなければならない。そこで、numaという変数にcountaの値を代入して、次の繰り返しに渡す。countaという変数は、次の繰り返しでまた、0からaを数えなければならないから、ここで0を代入して、初期化しておく
  ・内側のfor文の繰り返しが1回終わったら
   numa = counta
   counta = 0
++次の世代でも上と同じことを繰り返すが、集団内の対立遺伝子頻度は、前の世代の対立遺伝子頻度で決まる。

**2. 対立遺伝子aの初期値を自由に変更できるように、関数にしてしまう。 [#kd03c7e0]
これでは使いにくいので、aの値を自由に変更できる関数を定義してみましょう。「関数の定義」なんていうと難しそうですが、ようするに、作ったプログラムに名前をつけて、いろいろと数値を変えて解析できるようにすることです。

 drift1=function(a){       #関数定義の始まり
                              #上にあった、a=10 という命令は削除。この関数では、aの値を自由に変えられる  
  for(i in 1:30){             
    counta=0                  
    for(j in 1:20){           
      if ( runif(1) < a/20  ){  
       counta=counta+1         
      }
    }
    out=counta/20        
    print(out)                 
    a=counta                   
   }
 }                      #関数定義の終わり

さっきのプログラムの上下を関数を定義する関数であるfunction(){}で囲んで、オブジェクトに代入するだけですから、簡単です。この関数を実行するには、最初aの値を()の中に入力して、
 drift1(10)
**予習課題:Rを使った関数の定義 [#e6d9d800]
「関数の定義」なんていうと難しそうですが、ようするに、作ったプログラムに名前をつけて、いろいろと数値を変えて解析できるようにすることです。例えば、
 1から入力した数値までの全てを横一列に表示させるプログラムを作り
 displayという名前の関数として定義する
どうやるかというと、
 display=function(a){       #関数定義の始まり
  kekka=c()                 #kekkaに空ベクトルを代入して初期化
  for(i in 1:a){              #a回(iの値を1からaまで変化させる間)繰り返し
    kekka=append(kekka,i)     #kekkaというベクトルにiを要素として代入
  }
  print(kekka)              #kekkaの内容を表示
 }                          #関数定義の終わり
上の方で作ったプログラムの上と下を関数をfunction(){}で囲んで、オブジェクトに代入するだけですから、簡単です。この関数を実行するには、最初aの値を()の中に入力して、
 display(10)
とします。

↑を使って何回も実行してみると、結果がいろいろ変わるのがわかりますよね。
~そこで問題です。上の関数の定義方法に従って、入力した数までの合計値を計算するsumupという名前の関数を作成します。下の囲みの中の_の部分(1文字に対応するとは限らない)を埋めて、プログラムを完成して提出しなさい。
  sumup = ______       #関数sumpuを定義
    kotae = _          #kotaeを初期化
    _ (i in ___){      #1からaまで繰り返し
      kotae = _____    #kotaeにiの値を足したものとkotaeに代入
    }                  #繰り返し終了
   _____               #kotaeを表示
   }                   #関数定義の終了

**3.結果をグラフ表示。前につかったplot()関数 [#xdaae7e5]
では、せっかく結果が出たのだから、グラフにしてみましょう。でも、その前に、以前使ったplot()という関数を思い出してみましょう。
 x=c(1,2,3,4,5)
 plot(x)
plot()という関数は、ベクトルの内容をプロットしてくれるのでした。そうすると、今のdrift1関数の実行結果はどうやれば表示できるでしょうか?

 関数を実行した結果が全て、一つのオブジェクトにベクトルとして格納されていれば良い。例えば:
 0.6, 0.55, 0.65, 0.8, 0.95, 1, 1, 1, ...
これをやるには、上のout=count/20としているところを、次から次へとベクトルの要素を付け加えるようにすれば良さそうです。ベクトル要素を付け加える関数が
 append()
です。
 results=append(results, a/20)
と書けば、resultsというベクトルにa/20の値が追加されます。但し、ひとつだけ重要な注意があります。
 resultsというベクトルはあらかじめ存在していなければ、append()は使えない
つまり、for文を使って繰り返しを行う前に、
 results=c()
という命令で、空ベクトルを作っておく必要があるのです。

 では、まず、結果をresults()に入れてベクトルで返すような変更を、上のプログラムに加えて見ましょう

 drift2=function(a){ 
  results=c()       #空ベクトルを作る
  for(i in 1:30){             
    counta=0                  
    for(j in 1:20){           
      if ( runif(1) < a/20  ){  
       counta=counta+1         
      }
    }
    results=append(results, a/20)   #ここにあった out=counta/20 の代わりに、append()関数でベクトル作成
    a=counta                   
   }
     print(results)                 #printの文はfor文の外に出したことに注意!理由は分かりますよね
 }                      

これで
 [1] 0.50 0.60 0.80 0.70 0.55 0.50 0.35 0.40 0.20 0.30 0.1....
というベクトルが表示できました。これをplot()でグラフにするには、
 plot(drift2(10))
とやるだけです。


しかし。。。ちょっと待てよ?どうせなら、関数の中にplot()を入れてしまえばすぐにグラフが表示されるのでは?
 drift3=function(a){ 
  results=c()       #空ベクトルを作る
  for(i in 1:30){             
    counta=0                  
    for(j in 1:20){           
      if ( runif(1) < a/20  ){  
       counta=counta+1         
      }
    }
    results=append(results, a/20)   
    a=counta                   
   }
     plot(results)     #ここにあった print文の代わりに、plot()でグラフ表示
 }

グラフがすぐに表示できました!でも、点々では見にくいので、線で結んでみましょう。plot()のところを、
 plot(results, type="l")
とかえるだけです。

 drift4=function(a){ 
  results=c()       #空ベクトルを作る
  for(i in 1:30){             
    counta=0                  
    for(j in 1:20){           
      if ( runif(1) < a/20  ){  
       counta=counta+1         
      }
    }
    results=append(results, a/20)   
    a=counta                   
   }
     plot(results, type="l")     #ここにあった print文の代わりに、plot()でグラフ表示
 }

**4.何回もの計算結果を、一つのグラフにまとめて表示したい [#qa15e0db]
 上で作ったプログラムを何度も走らせてみると、グラフの形がどんどん変わります。これはこれで面白いのですが、グラフの軸が一定していないし、1つのグラフに結果が重ねて表示されないので、ちょっと感じがつかめませんね。

そこで、いっそのこと、この実験を20回ぐらい繰り返してみて、結果を1つのグラフに表示させることにしましょう。同じことを何度も繰り返すのですから、for文をもう一つ、外側に作ればいいって、容易に想像がつきますよね?

 drift5=function(a){ 
  for(i in 1:20){           #これまでのプログラムの外側に新しく作ったfor文。20回繰り返す。
    results=c()       
    for(j in 1:30){             
      counta=0                  
      for(k in 1:20){           
        if ( runif(1) < a/20  ){  
         counta=counta+1         
        }
      }
      results=append(results, a/20)   
      a=counta                   
     }
       plot(results, type="l") 
  }                        #新しく作ったfor文の終わり。ここまで繰り返し。
 }

さあ、走らせてみましょう。
 drift5(10)

あれ?なんか変ですね。最後は0.0で線が一本でるだけです。
 なぜだか分かりますか?
こたえは、aの値です。最初、aは10で与えられましたが、1集団分の繰り返しが終わった後、次の繰り返しの前に、下の数字に戻すのを忘れていました。

 drift5=function(a){ 
  firsta=a            #関数に渡された(つまり()の中に書かれた)aの値をfirstaというオブジェクトに保存
  for(i in 1:20){     #これまでのプログラムの外側に新しく作ったfor文。20回繰り返す。
    a=firsta          #繰り返しの最初に、aの値を初期値(firsta)に戻す
    results=c()       
    for(j in 1:30){             
      counta=0                  
      for(k in 1:20){           
        if ( runif(1) < a/20  ){  
         counta=counta+1         
        }
      }
      results=append(results, a/20)   
      a=counta                   
     }
       plot(results, type="l") 
  }                        #新しく作ったfor文の終わり。ここまで繰り返し。
 }

できました。実行してみましょう。ウーン。。。うまくいってるようなのですが、1回ずつ、グラフが変わっちゃいます。グラフを重ねて描くには、par(new=T) というコマンドをplot()の前に使います。
 
 drift5=function(a){ 
  firsta=a            #関数に渡された(つまり()の中に書かれた)aの値をfirstaというオブジェクトに保存
  for(i in 1:20){     #これまでのプログラムの外側に新しく作ったfor文。20回繰り返す。
    a=firsta          #繰り返しの最初に、aの値を初期値(firsta)に戻す
    results=c()       
    for(j in 1:30){             
      counta=0                  
      for(k in 1:20){           
        if ( runif(1) < a/20  ){  
         counta=counta+1         
        }
      }
      results=append(results, a/20)   
      a=counta                   
     }
       par(new=T)     #複数のグラフを重ね合わせる
       plot(results, type="l") 
  }                        #新しく作ったfor文の終わり。ここまで繰り返し。
 }

あれれ?そうか。始点の軸が固定されていないから、ずれちゃってますね。plot()関数にはylimというオプションがあって、y軸の目盛りを0から1に固定するには、次のように書きます。

 drift5=function(a){ 
  firsta=a            #関数に渡された(つまり()の中に書かれた)aの値をfirstaというオブジェクトに保存
  for(i in 1:20){     #これまでのプログラムの外側に新しく作ったfor文。20回繰り返す。
    a=firsta          #繰り返しの最初に、aの値を初期値(firsta)に戻す
    results=c()       
    for(j in 1:30){             
      counta=0                  
      for(k in 1:20){           
        if ( runif(1) < a/20  ){  
         counta=counta+1         
        }
      }
      results=append(results, a/20)   
      a=counta                   
     }
       par(new=T)     #複数のグラフを重ね合わせる
       plot(results, type="l", ylim=c(0,1))   #y軸の目盛りを0から1に固定する
  }                        #新しく作ったfor文の終わり。ここまで繰り返し。
 }

いよいよ完成にちかづいてきました。図が重なって見にくくなったら、
 >frame()
 か
 >plot.new()
で図を新しく書き直して下さい。


**5.もっと大きな集団サイズで解析してみたい。 [#u93d3778]
 何回かグラフを描かしてみると、わりとすぐに固定してしまうことがわかりますね。じゃあ、もっと、集団サイズがもっと大きかったらどうなるか気になってくるでしょ?

 どうすればよいか?プログラムの中で、集団サイズを20に指定しているところを100とかに変更してもいいのですが、どうせなら、関数に値を渡すときに、指定できれば、つまり、
 drift(繰り返し数, 世代数, 集団サイズ, 対立遺伝子の数)
とか指定して実行できれば、好きな大きさの集団で、好きな数だけ、シミュレーションを繰り返せますよね。さっきのプログラムで、数値で指定してあったところを変数に置き換えるだけですから、そんなに難しくなさそうです。

では、やってみましょう

 drift6=function(x, y, z, a){ 
  plot.new()         #ついでに、図を新しく書き直すという関数をここに追加しました
  firsta=a            
  for(i in 1:x){     #上のプログラムでは20でしたが、ここでは、x回繰り返す。
    a=firsta         
    results=c()       
    for(j in 1:y){   #上のプログラムでは30だったけど、ここではy世代繰り返す。           
      counta=0                  
      for(k in 1:z){ #上のプログラムでは20だったけど、ここでは集団サイズはz。
        if ( runif(1) < a/z  ){  #上のプログラムでは20だったけど、ここでは集団サイズはz。
         counta=counta+1         
        }
      }
      results=append(results, a/z)    #上のプログラムでは20だったけど、ここでは集団サイズはz。
      a=counta                   
     }
       par(new=T)     
       plot(results, type="l", ylim=c(0,1))  
  }                        
 }

できちゃいました。
あんまり大きい数字を入れると計算にすごく時間がかかります。途中で終了したいときは、 ESC キーを押してください。

**演習: [#v54b4118]
下のプログラムは遺伝的浮動をシミュレートするRのプログラムです。シミュレーションで観察する集団の数(num_repeats)、1集団あたり観察する世代数(num_generations)、集団サイズ(遺伝子数)(size_population)、0世代目における対立遺伝子aの数(num_a_allele)を与えて実行すれば、、ランダムに選ばれる遺伝子が、次世代の集団の遺伝子頻度にどのように影響するかを、シミュレートする集団の数だけグラフに(色つきで)表示することができます。下のプログラムを見て以下の問に答えなさい。

 drift= function(num_repeats,num_generations,size_population, num_a_allele){
	 results=c()
         a=num_a_allele
	 for(i in 1:【1】){
		  for(j in 1:【2】){
		      count_a=0
		       for(k in 1:size_population){
			    if ( runif(1) < a/【3】 ){
			     count_a=count_a+1
			    }
		       }
		       a=count_a
		       results=append(results, a/size_population)
		  }
		  a=num_a_allele
	 }
	 rmatrix=matrix(results, nrow=num_generations, ncol=num_repeats)
	 return(matplot(rmatrix, type="l"))
 }

-問1: プログラム中【1】~【3】に入る変数名を、下のリストから選びなさい
 num_repeats, num_generations, size_population, num_a_allele
--それぞれの変数は次のような意味を持っています
---num_repeats : シミュレーションを行う集団数(1つの集団についてある世代数だけ観察するという実験を、何回(何個の集団について)おこなうか)。つまり、何本の折れ線グラフを表示させるか
---num_generations : 1つの集団について何世代観察するか。x軸の長さになります。
---size_population : 集団のサイズ、つまり、1つの集団に含まれる遺伝子の数
---num_a_allele : aアリルの数(つまり、この値をnum_populationで割ったものが、0世代目でのaアリルの遺伝子頻度になる)

-問2: 上のプログラム中、【1】~【3】を問1で答えた変数で置き換え、次の2つの場合を実行しなさい。
 1. 実験の繰り返し数10回、1集団での観察世代数500世代、集団サイズ(遺伝子数)200, 初期状態での対立遺伝子aの数100
 2. 実験の繰り返し数10回、1集団での観察世代数100世代、集団サイズ(遺伝子数)20, 初期状態での対立遺伝子aの数10
 実行するための命令文と、結果のグラフを、1, 2のいずれの場合についても、課題提出ページに貼り付けなさい(注:1番目のシミュレーションの実行には、数分かかるかもしれません)
-問3: 上の2つのグラフを比較して分かったことを述べなさい。


-------------------------------
*時間があったら説明: いろんなシミュレーション [#he54915e]

**7.丸耳の表現型(aaで示されるもの)の集団内での表現型頻度をグラフで表示 [#o15e8af8]
 drift6=function(x, y, z, a){ 
  plot.new()         #ついでに、図を新しく書き直すという関数をここに追加しました
  firsta=a            
  for(i in 1:x){     #上のプログラムでは20でしたが、ここでは、x回繰り返す。
    a=firsta         
    results=c()
    results_p=c()       
    for(j in 1:y){              
      counta=0
      count_p=0
      count_p_type=0        
      for(k in 1:z){ 
        if ( runif(1) < a/z  ){  
         counta=counta+1
        }
        if (k%%2 != 0){              #jが奇数のとき
           if ( runif(1) < a/z  ){     #もし2つの遺伝子のうち最初のものがaならば
             count_p=count_p+1         #count_pの値を1増やす
           }
        } else {                     #jが偶数のとき
           if ( runif(1) < a/z  ){    #もし2つの遺伝子のうち最初のものがaならば
             count_p=count_p+1        #count_pの値を1増やす
           }
           if(count_p == 2){         #連続する奇数回・偶数回で合計したpの値が2ならば(つまり、aが2個だったら)
             count_p_type=count_p_type+1  #count_p_typeの値を1増やす(aaとう表現型が1つあると数える)
           }
           count_p=0                 #2個数え終わったら、count_pの値を初期化
        }
      }
      results=append(results, a/z)    
      results_p=append(results_p, count_p_type/(z/2))  #results_pに集団内のaaの頻度(count_p_type/z/2)を入れる
      count_p_type=0                                 #count_p_typeの値を初期化
      a=counta                   
     }
       par(new=T)     
       plot(results, type="l", ylim=c(0,1))  
       par(new=T)     
       plot(results_p, type="l", ylim=c(0,1), col="blue")  #aaの頻度を青線で表示する
  }                        
 }

**8.選択係数sで、丸耳の表現型(aa)を集団から排除してみよう [#zea292e6]
  drift6=function(x, y, z, a, s){ #選択係数sでaaが集団から排除される
  plot.new()         
  firsta=a            
  for(i in 1:x){     
    a=firsta         
    results=c()
    results_p=c()       
    for(j in 1:y){              
      counta=0
      count_p=0
      count_p_type=0        
      for(k in 1:z){ 
        if (k%%2 != 0){              #jが奇数のとき
           if ( runif(1) < a/z  ){     #もし2つの遺伝子のうち最初のものがaならば
             count_p=count_p+1         #count_pの値を1増やす
           }
        } else {                     #jが偶数のとき
           if ( runif(1) < a/z  ){    #もし2つの遺伝子のうち2番目のものがaならば
             count_p=count_p+1        #count_pの値を1増やす
           }
           if(count_p == 2){         #連続する奇数回・偶数回で合計したpの値が2ならば(つまり、aが2個だったら)
             if (runif(1) < s) {      #遺伝子型がaaのとき乱数を一つとって、それが選択係数より小さければ
               k=k-2                  #jの値から2を引いて
               count_p=0              #count_pを初期化し           
               next                   #強制的に次の繰り返し
             } else {
               count_p_type=count_p_type+1  #count_p_typeの値を1増やす(aaという表現型が1つあると数える)
             }
          }
           counta=counta+count_p
           count_p=0                 
        }
      }
      results=append(results, a/z)    
      results_p=append(results_p, count_p_type/(z/2))  #results_pに集団内のaaの頻度(count_p_type/z/2)を入れる
      count_p_type=0                                 #count_p_typeの値を初期化
      a=counta                   
     }
       par(new=T)     
       plot(results, type="l", ylim=c(0,1))  
       par(new=T)     
       plot(results_p, type="l", ylim=c(0,1), col="blue")  #aaの頻度を青線で表示する
  }                        
 }

**9.固定までにかかった世代数を求める関数 [#r6b6ba61]
 wtime=function(x, y, z, a){ 
 firsta=a            
 results_w=c()  
 for(i in 1:x){     
   a=firsta         
   results=c()     
   w_time=0
   for(j in 1:y){              
     counta=0                  
     for(k in 1:z){ 
       if ( runif(1) < a/z  ){  
        counta=counta+1         
       }
     }
     a=counta                   
     if((w_time==0) && ((a==0) || (a==z))) { #もしw_timeが空で、aが0かzに固定しているとき、
        w_time=j                             #w_timeにそのときに世代数jを入れる
     }
   }
   results_w=append(results_w, w_time)       #その集団における固定までの世代時間をresults_wに入れる
 }  
   return(results_w)                      
 }

**10.有限集団におけるヘテロ接合体頻度の変化 [#g5da17c3]
 drift6=function(x, y, z, a){ 
  plot.new()        
  firsta=a
  resultp_m=c()            
  for(i in 1:x){    
    a=firsta         
    results=c()
    results_p=c()       
    for(j in 1:y){              
      counta=0
      count_p=0
      count_p_type=0        
      for(k in 1:z){ 
        if ( runif(1) < a/z  ){  
         counta=counta+1
        }
      }
      results=append(results, a/z)    
      results_p=append(results_p, 2*(a/z)*(1-a/z))  #results_pに集団内のaaの頻度(count_p_type/z/2)を入れる
      a=counta                   
     }
     resultp_m=append(resultp_m, results_p)
       par(new=T)     
       plot(results, type="l", ylim=c(0,1), col="gray")  
  }                        
     rmatrix=matrix(resultp_m, nrow=y, ncol=x)
     hetero=c()
     for(i in 1:y) {
       hetero=append(hetero,mean(rmatrix[i,]))
     }
     par(new=T)
     plot(hetero, type="l", ylim=c(0,1), col="blue")
     par(new=T)
     curve(0.5*(1-1/z)^x, xlim=c(0,y), ylim=c(0,1), col="red")
 }