3S
  • Portfolio Top
  • Categories
  • Tags
  • Archives

マイクロアレイ実習1

マイクロアレイデータ解析¶

〜マイクロアレイを用いた網羅的遺伝子発現解析〜

  • 担当:程研究室
  • 実習のwiki:http://bit.ly/microarray-2019
  • 論文:Functional dissection of siRNA sequence by systematic DNA substitution: Modified siRNA with a DNA seed arm is a powerful tool for mammalian gene silencing with significantly reduced off-target effect

【目的】¶

 網羅的に遺伝子の発現を解析する手法であるマイクロアレイの原理、操作手順、解析方法について学ぶ。siRNAを導入した細胞からRNAを抽出し、マイクロアレイを行うことで、全mRNAの変動量を解析する。

【原理】¶

●RNAiとオフターゲット効果¶

 RNA interference(RNAi)とは「二本鎖RNA(哺乳類の場合、長さ21塩基程度のsiRNA(small interfering RNA)がよく使われる)がそれと相補的な配列を持つmRNAを配列特異的に切断することで遺伝子の発現を抑制する現象のこと」であり、その機構は多くの生物種で保存されているため、簡便に遺伝子機能を抑制する手法として広く利用されている。

 この時、RNAiにおいて、標的遺伝子だけでなく、siRNAのシードと呼ばれる領域(ガイド鎖の5'末端から2~8塩基目の領域)と相補的な配列を持つ多数のmRNA群に対しても抑制効果が認められ、オフターゲット効果と呼ばれている。

 オフターゲット効果による遺伝子抑制の程度は、「siRNAのシード領域がそれと相補的なRNAと塩基対合エネルギーの強さ」であることが明らかになっている。すなわち、対合エネルギーが大きいシードを持つsiRNAはオフターゲット効果が強い。

 今回の実習では、ビメンチンを標的としたsiRNA(siVM-270)及びsiVIM-270のガイド鎖のシード領域に化学修飾を導入したsiRNAを用いて、「siRNAが標的とするビメンチンの発現量」及び「オフターゲット効果の程度」にどれくらいの相違が生じるのかを、マイクロアレイを用いて網羅的に解析する。

●マイクロアレイ¶

 マイクロアレイはDNAチップとも呼ばれ、あらかじめ塩基配列のわかっている1本鎖DNAを基盤上に高密度に配置したものである。そこに蛍光標識したRNAをハイブリダイゼーションさせることで、サンプルで発現しているmRNAを網羅的に検出・定量できる。

RNAi マイクロアレイ

【方法】¶

●サンプル¶

 今回の実験で用いたサンプルは、HeLa細胞に下記のsiRNA(化学合成したもの)を導入して24時間後に回収したものである。なお、"mock"は、核酸を加えずにトランスフェクション操作のみを行ったものである。なお、シード領域を緑色にした。

サンプル 配列(ガイド鎖が上) seed配列(2-8)と相補的な配列 修飾
mock なし なし
RNA 5′-XXUUGAACUCGGUGUUGAUGGCG-3′
3′-AGAACUUGAGCCACAACUACCXX-5′
5′-GAGTTCA-3′
5′-GTTGATG-3′
なし
2OMe3 5′-XXUUGAACUCGGUGUUGAUGGCG-3′
3′-AGAACUUGAGCCACAACUACCXX-5′
同上 赤字部分に2'OMe修飾
2OMe5 5′-XXUUGAACUCGGUGUUGAUGGCG-3′
3′-AGAACUUGAGCCACAACUACCXX-5′
同上 赤字部分に2'OMe修飾
2OMe7 5′-XXUUGAACUCGGUGUUGAUGGCG-3′
3′-AGAACUUGAGCCACAACUACCXX-5′
同上 赤字部分に2'OMe修飾
LNA3 5′-XXUUGAACUCGGUGUUGAUGGCG-3′
3′-AGAACUUGAGCCACAACUACCXX-5′
同上 赤字部分にLNA修飾
LNA7 5′-XXUUGAACUCGGUGUUGAUGGCG-3′
3′-AGAACUUGAGCCACAACUACCXX-5′
同上 赤字部分にLNA修飾

●ウェット¶

 今回の実験はドライの方がメインなので、省略する。なお、以下のファイル形式で結果が得られた(とする)。中身は後述。

ファイル名 サンプル
US91503671_253949442637_S01_GE1_105_Dec08_1_1.txt mock
US91503671_253949442637_S01_GE1_105_Dec08_1_2.txt RNA
US91503671_253949442637_S01_GE1_105_Dec08_1_3.txt 2OMe3
US91503671_253949442637_S01_GE1_105_Dec08_1_4.txt 2OMe5
US91503671_253949442637_S01_GE1_105_Dec08_2_1.txt mock
US91503671_253949442637_S01_GE1_105_Dec08_2_2.txt 2OMe7
US91503671_253949442637_S01_GE1_105_Dec08_2_3.txt LNA3
US91503671_253949442637_S01_GE1_105_Dec08_2_4.txt LNA7

【解析】¶

 それでは、解析を始める。が、その前に今回の目的をもう一度。

 siRNAのオフターゲット効果は、本来意図したmRNA(今回はビメンチン)以外のmRNAとも結合して発現を抑制してしまうという困った性質である。(医薬品の場合では重大な副作用を起こしてしまう可能性がある)従って、どのような場合にオフターゲットが起こるのか(本当にシード領域なのか)、オフターゲットによってどの程度抑制されるのかを調べていく。

Index

  1. 全データサンプルのデータを一つにまとめる
  2. 信頼できるデータのみを残す
  3. XYプロット
  4. MAプロット
  5. mockとの比較
  6. normalization
  7. ビメンチン(vimentin)の発現量を調べる
  8. ビメンチン以外をコードするmRNAの発現量を調べる
  9. seedマッチする遺伝子群の累積度数を調べる
  10. 1-8以外の7merの寄与を調べる
  11. 7mer以外で考える
  12. 寄与率を調べる
In [1]:
! python --version
Python 3.6.8 :: Anaconda, Inc.
In [2]:
# 見栄えの問題
import warnings
warnings.filterwarnings('ignore')

1. 全データサンプルのデータを一つにまとめる

In [3]:
import os
import numpy as np
import pandas as pd
In [4]:
# データの形式
pd.read_csv("US91503671_253949442637_S01_GE1_105_Dec08_1_1.txt",sep="\t").head(15)
Out[4]:
TYPE text text.1 text.2 text.3 integer float float.1 text.4 text.5 ... float.63 integer.58 integer.59 float.64 text.23 integer.60 integer.61 integer.62 integer.63 integer.64
0 FEPARAMS Protocol_Name Protocol_date Scan_Date Scan_ScannerName Scan_NumChannels Scan_MicronsPerPixelX Scan_MicronsPerPixelY Scan_OriginalGUID Grid_Name ... QCMetrics_MinReproducibility QCMetrics_Formulation QCMetrics_EnableDyeFlip QCMetrics_PercentileValueForSignal FeatureExtractor_Version FeatureExtractor_SingleTextFileOutput FeatureExtractor_JPEGDownSampleFactor FeatureExtractor_ColorMode FeatureExtractor_QCReportType FeatureExtractor_OutputQCReportGraphText
1 DATA GE1_105_Dec08 (Read Only) 21-Nov-2008 12:35 06-12-2015 10:27:24 Agilent Technologies Scanner G2505C US91503671 1 2 2 baf1def2-6267-4afa-aec5-1e4404acbc9f ExternalFullGEML039494_D_F_20120628 ... 50 2 0 75 10.5.1.1 1 4 0 0 0
2 * NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3 TYPE float float float integer integer float float float integer ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
4 STATS gDarkOffsetAverage gDarkOffsetMedian gDarkOffsetStdDev gDarkOffsetNumPts gSaturationValue gAvgSig2BkgeQC gAvgSig2BkgNegCtrl gRatioSig2BkgeQC_NegCtrl gNumSatFeat ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
5 DATA 5.51703 5.51703 2.14558 0 779055 61.087 3.78901 16.1221 0 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
6 * NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
7 TYPE integer integer integer text text integer text integer text ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
8 FEATURES FeatureNum Row Col accessions chr_coord SubTypeMask SubTypeName Start Sequence ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
9 DATA 1 1 1 NaN 260 BrightCorner 0 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
10 DATA 2 1 2 NaN 66 Structural 0 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
11 DATA 3 1 3 NaN 66 Structural 0 NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
12 DATA 4 1 4 ref|NM_015987|ens|ENST00000014930|gb|AF117615|... hs|chr12:13127906-13127847 0 NaN 1100 AAGGGGGAAAATGTGATTTGTGCCTGATCTTTCATCTGTGATTCTT... ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
13 DATA 5 1 5 ref|NM_080671|ens|ENST00000281830|tc|THC2655788 hs|chr2:223920197-223920256 0 NaN 2802 GCAAGTCTCTCTGCACCTATTAAAAAGTGATGTATATACTTCCTTC... ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
14 DATA 6 1 6 ref|NM_178466|ens|ENST00000375454|ens|ENST0000... hs|chr20:31812208-31812267 0 NaN 533 CATTCCATAAGGAGTGGTTCTCGGCAAATATCTCACTTGAATTTGA... ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

15 rows × 155 columns

※ 0-7行目が各配列のメタデータ、8行目からが実際のデータになっていることがわかる。

 全てのサンプルデータのフォーマットは等しい。従って、以下の情報は一度だけ抜き取れば良い。

カラム名 内容
FeatureNum スポットの番号
ControlType positive control は 1, negative control は -1 それ以外(解析で使う)は 0
ProbeName プローブ名
GeneName 遺伝子名
SystematicName 遺伝子名

 それに対して、以下二つの情報は各サンプルごとに残す必要がある。

カラム名 内容
gProcessedSignal green(Cy-3)のシグナル強度(=発現量)
gIsWellAboveBG シグナルがバックより十分高いか?(=信頼できるデータか)
In [5]:
# 実習ファイルの形式
! tree | grep .txt
├── US91503671_253949442637_S01_GE1_105_Dec08_1_1.txt
├── US91503671_253949442637_S01_GE1_105_Dec08_1_2.txt
├── US91503671_253949442637_S01_GE1_105_Dec08_1_3.txt
├── US91503671_253949442637_S01_GE1_105_Dec08_1_4.txt
├── US91503671_253949442637_S01_GE1_105_Dec08_2_1.txt
├── US91503671_253949442637_S01_GE1_105_Dec08_2_2.txt
├── US91503671_253949442637_S01_GE1_105_Dec08_2_3.txt
├── US91503671_253949442637_S01_GE1_105_Dec08_2_4.txt
In [6]:
USE_COLS1 = ['FeatureNum', 'ControlType', 'ProbeName', 'GeneName', 'SystematicName']
USE_COLS2 = ['gProcessedSignal', 'gIsWellAboveBG']
In [7]:
samples = ['mock(1)','RNA','2OMe3','2OMe5','mock(5)','2OMe7','LNA3','LNA7']
In [8]:
# ※注意:sorted をつける必要あり!!(∵ os.listdir() の順番はtreeの順番とは異なる。)
file_paths = sorted([path for path in os.listdir() if path[-4:] == ".txt"])
In [9]:
# 確かに tree と同じ順番になっている事を確認。
file_paths
Out[9]:
['US91503671_253949442637_S01_GE1_105_Dec08_1_1.txt',
 'US91503671_253949442637_S01_GE1_105_Dec08_1_2.txt',
 'US91503671_253949442637_S01_GE1_105_Dec08_1_3.txt',
 'US91503671_253949442637_S01_GE1_105_Dec08_1_4.txt',
 'US91503671_253949442637_S01_GE1_105_Dec08_2_1.txt',
 'US91503671_253949442637_S01_GE1_105_Dec08_2_2.txt',
 'US91503671_253949442637_S01_GE1_105_Dec08_2_3.txt',
 'US91503671_253949442637_S01_GE1_105_Dec08_2_4.txt']
In [10]:
# 基盤となるデータフレーム 
df_all = pd.read_csv("US91503671_253949442637_S01_GE1_105_Dec08_1_1.txt",sep="\t",header=9, engine='python')[USE_COLS1]
all_index = df_all.index

for path,sample in zip(file_paths,samples):
    df = pd.read_csv(path,sep="\t",header=9, engine='python')[USE_COLS2]
    
    # gIsWellAboveBG が 1 のもののみを抽出する。
    select_index = df[(df.gIsWellAboveBG==1)].index
    all_index = set(all_index) & set(select_index)
    
    # gIsWellAboveBG はもういらないのでシグナル強度のみを残す。
    df = df[['gProcessedSignal']]
    df.columns = [sample]
    
    # 連結する
    df_all = pd.concat([df_all, df], axis=1)
In [11]:
print("データ数: {}".format(len(df_all)))
データ数: 62976
In [12]:
selected_index = sorted(list(all_index))
In [13]:
df_output = df_all.loc[selected_index,:]

2. 信頼できるデータのみを残す

 発現量が少なく、アレイで検出できなかったものは、glsWellAboveBG の値が 0 となっている。今回は、全てのサンプルで glsWellAbove の値が 1 となっているもののみを解析の対象とする。また、 ControlType が 0 以外のものはコントロールのプローブなので、解析の対象から外す。

In [14]:
df_output = df_output[df_output.ControlType == 0]
In [15]:
print("データ数: {}".format(len(df_output)))
データ数: 21511
In [16]:
# 一度保存
df_output.reset_index(drop=True).to_excel("result.xlsx", index=False)

3. XYプロット

  • サンプル X の gProcessedSignal の値(以下 $X$ )を横軸
  • サンプル Y の gProcessedSignal の値(以下 $Y$ )を縦軸
In [17]:
import seaborn as sns
import matplotlib.pyplot as plt
In [18]:
sns.pairplot(df_output[samples])
plt.show()

ここで、大体直線上に並んでいることがわかる。従って、「大半のmRNAは」シード領域の修飾の違いに影響を受けていないことがわかる。(これがnormalizationを行うことの根拠になる。)

4. MAプロット

サンプル $X$ (大抵はコントロール)の場合とサンプル $Y$ の場合の発現量の増減を見ます。

  • $\log_{10}(XY)$ を横軸
  • $\log_{2}(Y/X)$ を縦軸
In [19]:
def MAplot(df,col_x,col_y,col_c=None,cdict=None,title=True,axis=True,ymin=None,ymax=None,vim=True):
    # MAプロットの変数を定義
    X=df[col_x].values
    Y=df[col_y].values
    row = np.log10(X*Y)
    col = np.log2(Y/X)
    
    # 色を分ける場合は、カラム(col_c)と対応する色(cdict)を指定
    if col_c:
        group=df[col_c].values
        
        for g in np.unique(group):
            ix = np.where(group==g)
            plt.scatter(row[ix], col[ix], s=1, c=cdict[g],label=g)
    else:
        plt.scatter(row, col, s=1)
    
    # y軸の範囲[ymin, ymax]を指定
    plt.ylim(ymin,ymax)
    
    # +1,0,-1に水平線を描画
    plt.hlines(y=0, xmin=min(row), xmax=max(row), colors='r', linewidths=2)
    plt.hlines(y=1, xmin=min(row), xmax=max(row), colors='r', linewidths=1)
    plt.hlines(y=-1,xmin=min(row), xmax=max(row), colors='r', linewidths=1)
    
    # タイトルを入れる
    if title: plt.title("MA plot $X$ = {}, $y$ = {}".format(col_x, col_y))
    
    # 軸の名前を入れる
    if axis: 
        plt.xlabel("$\log_{10}XY$")
        plt.ylabel("$\log_{2}(Y/X)$")
    
    # ビメンチンだけ別に描画
    if vim:        
        df_vim = df[df.GeneName == "VIM"]
        vim_x = df_vim[col_x]
        vim_y = df_vim[col_y]
        vim_row = np.log10(vim_x*vim_y)
        vim_col = np.log2(vim_y/vim_x)
        plt.scatter(vim_row, vim_col, s=5, c="black", marker="*", label="vimentin")
In [20]:
N = len(samples)
fig = plt.figure(figsize=(16, 16))

for j,col_y in enumerate(samples):
    for i,col_x in enumerate(samples):
        if j<i: continue # 修飾と修飾をMAプロットで比較する意味があるかはわからないが一応
        plt.subplot(N, N, j*N + i+1)
        MAplot(df_output,col_x,col_y,title=None,axis=None)
        if i==0: plt.ylabel(col_y)
        if j==len(samples)-1: plt.xlabel(col_x)
plt.show()

5. mockとの比較

 ここまでサンプル全体を概観したので、具体的に見ていきます。

●replicate 間でX-YプロットおよびMAプロットを作成¶

In [21]:
sns.pairplot(df_output[["mock(1)","mock(5)"]])
plt.show()
In [22]:
MAplot(df_output,"mock(1)","mock(5)")
plt.show()

●異なるサンプル間でX-YプロットおよびMAプロットを作成¶

In [23]:
# mock2つを並べてプロット
def mockplot(df,col_y,col_c=None,cdict=None,title=True,axis=True,ymin=None,ymax=None,vim=True):
    fig = plt.figure(figsize=(12,4))
    plt.subplot(1,2,1)
    MAplot(df,"mock(1)",col_y,col_c=col_c,cdict=cdict,title=title,axis=axis,ymin=ymin,ymax=ymax,vim=vim)
    plt.subplot(1,2,2)
    MAplot(df,"mock(5)",col_y,col_c=col_c,cdict=cdict,title=title,axis=axis,ymin=ymin,ymax=ymax,vim=vim)
In [24]:
# mock-RNA

# X-Y plot
sns.pairplot(df_output[["mock(1)","mock(5)","RNA"]])
plt.show()

# MA plot
mockplot(df_output, col_y="RNA")
plt.show()

6. normalization

 データの前処理において一般的な手法として、データの正規化がある。これは、アレイ間の全体的なシグナル強度の差を補正するために必要な操作であり、いくつかの手法がある。ここでは、以下の二つの手法を紹介する。
※ ただし、今回扱っているデータはかなり理想的なデータであるため、何もしない。できるだけデータに手を加えたくないやん。

In [25]:
raw_data = df_output[samples]
In [26]:
raw_data.shape
Out[26]:
(21511, 8)

75%tile法¶

各サンプルごとに、発現量の値を順番に並べ替え、発現量の小さい方から数えて順位75%に位置するものの値を求める。
この75%tileの値は通常サンプルごとに異なるが、それらの相乗平均 $a$ を求める。
各サンプルごとに、全プローブの値に 「$a$/そのサンプルにおける75%tileの値」をかける(つまり、全サンプルで75%tile値を $a$ に揃える。)

In [27]:
# 相乗平均を求める
from scipy.stats.mstats import gmean
In [28]:
tile_75s = [sorted(raw_data[col])[int(len(raw_data)*0.75)] for col in samples]
In [29]:
a = gmean(tile_75s)
In [30]:
tile_75_data = a * df_output[samples]/tile_75s
In [31]:
tile_75_data.shape
Out[31]:
(21511, 8)

quantile法¶

各サンプルごとに、発現量の値を順番に並べ替え、各順位の値をそれぞれ同順位のシグナル値の相乗平均で置き換える。
その結果、全サンプルで分布が同一になる。

In [32]:
quantile_data = gmean(np.array([sorted(raw_data[col]) for col in samples]),axis=0)
In [33]:
quantile_data.shape
Out[33]:
(21511,)

7. ビメンチン(vimentin)の発現量を調べる

「修飾によってビメンチンの抑制具合が異なるか」を調べる。

In [34]:
X = [i for i in range(len(samples))]
Y = df_output[df_output.GeneName == "VIM"][samples].values[0]
plt.xticks(X,samples)
plt.ylabel("gProcessedSignal")
plt.bar(X,Y)
plt.title('The relationship between \n"sRNA modification" and "gProcessedSignal"')
plt.show()

"mock"と比較することにより、LNA7を除いてビメンチンの発現を調節できていることがわかる。

8. ビメンチン以外をコードするmRNAの発現量を調べる

 ビメンチンの発現を見事に調節できていることがわかる。ここで、理論的には、siRNAのシード領域と相補的な配列を持つmRNA群に対しても抑制効果が起こる。このオフターゲット効果には「配列特異性」や「修飾特異性」があるのかを調べる。

 siRNAのガイド鎖のシード領域と相補的な配列は "5′-GAGTTCA-3′" であった。そこで、この配列を持つmRNAをseedmatchというサイトで調べ、seedmatch.xlsx というExcelファイルで保存する。

In [35]:
df_sm = pd.read_excel("seedmatch.xlsx")
In [36]:
# データ形式の確認
df_sm.head(3)
Out[36]:
[searchseq] [GAGTTCA]
0 NM_001004713 1
1 NM_173860 1
2 NM_001005493 1
In [37]:
print("データ数: {}".format(len(df_sm)))
データ数: 3646
In [38]:
# マージするためにdf_outputとカラム名を揃える。(なお、N_seedはシード領域の配列をいくつ含むか)
df_sm.columns = ["SystematicName","N_seed"]
In [39]:
df_with_Nseed = pd.merge(df_output,df_sm,on="SystematicName", how="left").fillna(0)
In [40]:
df_with_Nseed.groupby("N_seed").size()
Out[40]:
N_seed
0.0    19683
1.0     1613
2.0      184
3.0       17
4.0       14
dtype: int64
In [41]:
# 先にN_seedが小さいものからプロットすることで、グラフを見やすくする。
df_with_Nseed_sorted = df_with_Nseed.sort_values(by="N_seed")
In [42]:
color_dict = {0: "#EAECEE", 1:"#FBEEE6", 2:"#EB984E",3:"#873600",4:"#641E16"}
以下のプロットでは、見やすさを重視するため、適当にy軸の範囲を[-1,1]と決めてしまっています。
本来であればこういったことはせず、信頼度に基づいて(X,Yの値が小さければ誤差が出やすいはずだ、など)外れ値を除くべきです。
In [43]:
mockplot(df_with_Nseed_sorted,col_y="RNA",col_c="N_seed",cdict=color_dict,ymin=-1,ymax=1)
plt.legend()
plt.show()

↑かなりオフターゲット効果が起きている…。

In [44]:
mockplot(df_with_Nseed_sorted,"2OMe3",col_c="N_seed",cdict=color_dict,ymin=-1,ymax=1)
plt.legend()
plt.show()

↑比較的抑えめ。

In [45]:
mockplot(df_with_Nseed_sorted,"2OMe5",col_c="N_seed",cdict=color_dict,ymin=-1,ymax=1)
plt.legend()
plt.show()

↑これもかなりオフターゲット効果が起きている…。

In [46]:
mockplot(df_with_Nseed_sorted,"LNA3",col_c="N_seed",cdict=color_dict,ymin=-1,ymax=1)
plt.legend()
plt.show()

↑かなり抑えめ。


オフターゲット効果について¶

ここから、オフターゲット効果について調べる。
そのため、ここからは修飾を加えていないRNAと、mock(誤差を減らすため平均値を利用)のデータのみに注目する。

9. seedマッチする遺伝子群の累積度数を調べる

In [47]:
# mockは、平均値を利用する。
df_with_Nseed["mock"] = df_with_Nseed[["mock(1)","mock(5)"]].mean(axis=1)
In [48]:
# 発現量を調べる。
df_with_Nseed["log2(siRNA/mock)"] = np.log2(df_with_Nseed["RNA"]/df_with_Nseed["mock"])
In [49]:
df_signal = df_with_Nseed.sort_values(by="log2(siRNA/mock)")
In [50]:
signal_seed = df_signal[df_signal["N_seed"]!=0]["log2(siRNA/mock)"].values
signal_no_seed = df_signal[df_signal["N_seed"]==0]["log2(siRNA/mock)"].values
In [51]:
plt.plot(signal_no_seed,[(i+1)/len(signal_no_seed) for i in range(len(signal_no_seed))], label="others")
plt.plot(signal_seed,[(i+1)/len(signal_seed) for i in range(len(signal_seed))], label="have seed regions")
plt.title('The difference between\n"no seed regions" and "have seed resions"')
plt.xlabel("$\log_{2}(siRNA/mock)$")
plt.ylabel("Cumulative frequency")
plt.legend()
plt.grid()
plt.vlines(x=0, ymin=0, ymax=1, colors='black', linewidths=1)
plt.xlim(-1,1)
plt.show()

確かにシード領域を含んだ方ものの方が発現が抑制されている。じゃあ、シード領域を複数含むもの抑制されやすいのでは??

In [52]:
signal_no_seed = df_signal[df_signal["N_seed"]==0]["log2(siRNA/mock)"].values
signal_1_seed  = df_signal[df_signal["N_seed"]==1]["log2(siRNA/mock)"].values
signal_2_seed  = df_signal[df_signal["N_seed"]==2]["log2(siRNA/mock)"].values
signal_3_seed  = df_signal[df_signal["N_seed"]==3]["log2(siRNA/mock)"].values
signal_4_seed  = df_signal[df_signal["N_seed"]==4]["log2(siRNA/mock)"].values
In [53]:
plt.plot(signal_no_seed,[(i+1)/len(signal_no_seed) for i in range(len(signal_no_seed))], label="others")
plt.plot(signal_1_seed,[(i+1)/len(signal_1_seed) for i in range(len(signal_1_seed))], label="have 1 seed regions")
plt.plot(signal_2_seed,[(i+1)/len(signal_2_seed) for i in range(len(signal_2_seed))], label="have 2 seed regions")
plt.plot(signal_3_seed,[(i+1)/len(signal_3_seed) for i in range(len(signal_3_seed))], label="have 3 seed regions")
plt.plot(signal_4_seed,[(i+1)/len(signal_4_seed) for i in range(len(signal_4_seed))], label="have 4 seed regions")
plt.title('The difference between\n"no seed regions" and "have seed resions"')
plt.xlabel("$\log_{2}(siRNA/mock)$")
plt.ylabel("Cumulative frequency")
plt.legend()
plt.grid()
plt.vlines(x=0, ymin=0, ymax=1, colors='black', linewidths=1)
plt.xlim(-1,1)
plt.show()

データ数が少ないので分布がガタガタになっているが、そうでもなさそう。

10. 1-8以外の7merの寄与を調べる

もともとMicroarray analysis shows that some microRNAs downregulate large numbers of target mRNAsなどのモチーフ解析の結果からseedの2-8の領域が発現の抑制に効果があることは知られていたため、おそらく正しいのだが、果たしてseedの2-8領域だけなのかが気になったので、他のシード領域も調べて見る。なお、"7mer"というのは固定する。

In [54]:
df_output["mock"] = df_output[["mock(1)","mock(5)"]].mean(axis=1)
In [55]:
df_output["log2(siRNA/mock)"] = np.log2(df_output["RNA"]/df_output["mock"])
In [56]:
# 毎回 seedmatch のGUIで検索するのは面倒なので、リクエストを飛ばすことにする。
import requests
import re
In [57]:
def seedNmer(df, N, match_array, arrayname="", return_data=False):
    """
    関数の概要:色々な領域のNmerの発現量を調べる。
    @param df         :元となるデータフレーム 
    @param N          :領域の長さ
    @param match_array:ガイド鎖やパッセンジャー鎖のシード領域と相補的なmRNAの配列(5'-3')
    """
    PATTERNS = r'\n(.+)\t([0-9]+)'
    GMEANS = []
    COLNAMES = []
    LENGTH = len(match_array)
    df_Nmer = df.sort_values(by="log2(siRNA/mock)")
    plt.figure(figsize=(12,8))
    
    for p in reversed(range(len(match_array)+1)):
        colname = "{}-{}mer({}-{})".format(arrayname, N,LENGTH-p+1,LENGTH-p+N)
        COLNAMES.append(colname)

        # "seedmatch"にリクエスト飛ばしてseed領域に対応する配列を検索
        array = match_array[p-N:p]
        r = requests.post('http://atlas.rnai.jp/seedmatch/seedmatch.cgi', data={"seedseq": array})
        df_mRNA = pd.DataFrame(re.findall(PATTERNS, r.text))
        df_mRNA.columns=["SystematicName", colname]

        # マージ
        df_Nmer = pd.merge(df_Nmer, df_mRNA, on="SystematicName", how="left").fillna(0)
        # マッチする配列を持っているものを抜き出して
        signal_7mer = df_Nmer[df_Nmer[colname]!=0]["log2(siRNA/mock)"].values
        GMEANS.append(np.mean(signal_7mer))
        length = len(signal_7mer)
        # 累積密度をプロット
        plt.plot(signal_7mer,[(i+1)/length for i in range(length)], label=colname + ": {}".format(length))

        if p-N==0: break
    
    #=== プロット後処理 ===
    plt.title('The difference between\n"seed match resions" and "Expression levels"')
    plt.xlabel("$\log_{2}(siRNA/mock)$")
    plt.ylabel("Cumulative frequency")
    plt.grid()
    plt.vlines(x=0, ymin=0, ymax=1, colors='black', linewidths=2)
    plt.legend()
    plt.xlim(-1,1)
    plt.show()
    
    #===  ===
    X = [i for i in range(len(GMEANS))]
    label_before = [i for i in range(len(GMEANS)) if i %2 == 0]
    label_after  = ["{}-{}".format(p+1,p+N) for p in range(len(GMEANS)) if p %2 == 0]

    plt.barh(X,GMEANS)
    plt.title('The difference between\n"seed match resions" and "Expression levels"')
    plt.xlabel("7mer position")
    plt.ylabel("average $\log_{2}(siRNA/mock)$")
    plt.yticks(label_before,label_after)
    plt.show()
    
    if return_data: 
        return (df_Nmer, COLNAMES)

ガイド鎖¶

In [58]:
guide_array   = "UUGAACUCGGUGUUGAUGGCG" # 5'-3'
g_match_array = "CGCCATCAACACCGAGTTCAA" # 5'-3'
In [59]:
df_guide_7mer, guide_7mer_colnames = seedNmer(df_output, 7, g_match_array, arrayname="guide", return_data=True)

 確かに2-8番目の7merには特出した傾向がありそうだが、1-7番目の7merをはじめとしたそれ以外の7merにも抑制効果が働いていそう。

In [60]:
df_guide_7mer[guide_7mer_colnames].head(3)
Out[60]:
guide-7mer(1-7) guide-7mer(2-8) guide-7mer(3-9) guide-7mer(4-10) guide-7mer(5-11) guide-7mer(6-12) guide-7mer(7-13) guide-7mer(8-14) guide-7mer(9-15) guide-7mer(10-16) guide-7mer(11-17) guide-7mer(12-18) guide-7mer(13-19) guide-7mer(14-20) guide-7mer(15-21)
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 2 2 0 0 0 0 0 0 0 0 0 1 0 0 0
2 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0

 ※このデータは「12. 寄与率を調べる」で用いる。

パッセンジャー鎖¶

In [61]:
passenger_array = "CCAUCAACACCGAGUUCAAGA" # 5'-3'
p_match_array   = "TCTTGAACTCGGTGTTGATGG" # 5'-3'
In [62]:
seedNmer(df_output, 7, p_match_array, arrayname="passenger")

11. 7mer以外で考える

 シード領域の長さを長くしたり短くしたりした場合にどうなるのかを調べる。

In [63]:
seedNmer(df_output, 8, g_match_array, arrayname="guide")

8merでは一致する配列が少ないため関係性が掴みづらいが、やはり2-8領域が一致している配列は抑制されやすい傾向がありそうだ。

In [64]:
seedNmer(df_output, 5, g_match_array, arrayname="guide")

5merでは一致する配列がたくさんあり、発現量の違いが打ち消されている。(とはいえやはり2-8領域が一致している配列は抑制されやすい)

12. 寄与率を調べる

 モデルに予測させてみて、「どの特徴量を参考にした??」って聞けば、変数の重要度がわかるという流れ。今回は解釈のしやすい決定木を用いてパラメータも適当に決めてサクッと学習させてみた。

In [65]:
df_output.head(3)
Out[65]:
FeatureNum ControlType ProbeName GeneName SystematicName mock(1) RNA 2OMe3 2OMe5 mock(5) 2OMe7 LNA3 LNA7 mock log2(siRNA/mock)
3 4 0 A_23_P117082 HEBP1 NM_015987 12566.870 12356.960 12896.740 12860.240 12416.270 13869.810 14213.960 13553.84 12491.5700 -0.015631
8 9 0 A_21_P0000509 SNAR-G2 NR_024244 122723.700 117958.900 118623.000 128495.100 117447.400 124273.000 113802.500 107326.70 120085.5500 -0.025778
9 10 0 A_21_P0000744 LOC100506844 NR_038269 1234.146 1281.739 1128.132 1199.297 1251.119 1141.723 1302.718 1264.15 1242.6325 0.044703
In [66]:
from sklearn.ensemble import RandomForestRegressor
from sklearn import preprocessing

tree = RandomForestRegressor(random_state=0, max_depth=15)

x = df_guide_7mer[guide_7mer_colnames].values.astype(float)
y = df_guide_7mer["log2(siRNA/mock)"].values.astype(float)

tree.fit(x, y)
/Users/iwasakishuto/.pyenv/versions/anaconda3-5.0.1/lib/python3.6/site-packages/sklearn/ensemble/weight_boosting.py:29: DeprecationWarning: numpy.core.umath_tests is an internal NumPy module and should not be imported. It will be removed in a future NumPy release.
  from numpy.core.umath_tests import inner1d
Out[66]:
RandomForestRegressor(bootstrap=True, criterion='mse', max_depth=15,
           max_features='auto', max_leaf_nodes=None,
           min_impurity_decrease=0.0, min_impurity_split=None,
           min_samples_leaf=1, min_samples_split=2,
           min_weight_fraction_leaf=0.0, n_estimators=10, n_jobs=1,
           oob_score=False, random_state=0, verbose=0, warm_start=False)
In [67]:
plt.scatter(y,tree.predict(x), s=1)
plt.title('predicted "$\log_2(siRNA/mock)$" and answer "$\log_2(siRNA/mock)$"')
plt.ylabel("answer")
plt.xlabel("predict")
plt.show()
In [68]:
n_features = len(guide_7mer_colnames)
plt.figure(figsize=(12, 8))
plt.barh(range(n_features), tree.feature_importances_ , align='center')
plt.yticks(np.arange(n_features), guide_7mer_colnames)
plt.title("importances for predict the Expression levels")
plt.show()

 やはり、siRNAの2-8の7mer領域は強力に影響を与えていることがわかる。また、微妙な違いではあるが、端の配列とのマッチングの方がオフターゲット効果へのい影響が高そう。

In [ ]:
 

  • « ゲノム配列解析論Ⅱ 第2回
  • 細胞分子生物学Ⅰ 第10回 »
hidden
Table of Contents
Published
Jun 18, 2019
Last Updated
Jun 18, 2019
Category
生命科学基礎実験
Tags
  • 3S 95
  • 生命科学基礎実験 14
Contact
Other contents
  • Home
  • Blog
  • Front-End
  • Kerasy
  • Python-Charmers
  • Translation-Gummy
    • 3S - Shuto's Notes
    • MIT
    • Powered by Pelican. Theme: Elegant