Rスクリプト(GO) - yoshida1983/protc2026 GitHub Wiki
PCA・クラスタリングの続きとして、GO(Gene Ontology)のエンリッチメント解析を行います。表計算ソフトは使わず、Rだけで進めます。
目標:次の2つのセットで、サンプルごとにエンリッチした GO term が、どれだけ異なるかを比べます。
- 奇数番号のサンプル(A1, B3, C5, D7):各班で異なるタグ由来のサンプル
- 偶数番号のサンプル(A2, B4, C6, D8):同じライン由来のサンプル
進め方
- 同じプロジェクト、同じRの画面で続けます。PCA・クラスタリングで作った
merged(GFPを除いたもの、Scoreが0のものは0で置換済み)と、sample_names、sample_no、even_samplesを使います - GO解析では、Score の値は使いません。検出されたかどうか(Score > 0)だけを使います
GO解析の準備
- 1つ前のコマ(Mascotと同じコマ)で、UniProtのブラウザで開いて、Mascotの結果といっしょにダウンロードした対応表を、プロジェクトのフォルダにコピー&ペースト
- シロイヌナズナの reviewed エントリの一覧です(ファイル名:
uniprotkb_organism_id_3702_AND_reviewed_(ダウンロードした日).tsv)
- シロイヌナズナの reviewed エントリの一覧です(ファイル名:
- RStudio の【右下】「Files」に、csvファイルといっしょに、表示されていることを確認
対応表の読み込み(Accession → AGIコード)
Mascotの Accession(RCA_ARATH など)を、GO解析に使うAGIコード(AT2G39730 など)に変換します。
- 対応表のファイルを探して、読み込み
- ファイル名の日付は、ダウンロードした日によって変わるので、名前の最初の部分(
uniprotkb_)で探します
- ファイル名の日付は、ダウンロードした日によって変わるので、名前の最初の部分(
uni_file <- list.files(pattern = "^uniprotkb_.*\\.tsv(\\.gz)?$")
uni_file
if (length(uni_file) != 1) stop("対応表のファイルが1つではありません。Filesを確認してください")
uni <- read_tsv(uni_file, show_col_types = FALSE)
names(uni) # 列名を確認
- 「Entry Name」の列と、AGIコードの列(Gene Names (ordered locus))から、対応表を作る
- UniProtのAGIコードは
At2g39730のような形なので、大文字(AT2G39730)にそろえます - 1つのエントリに複数のAGIコードがある場合(
At1g67370/At1g67380など)は、すべて使います(別の行になります)
- UniProtのAGIコードは
id_col <- grep("Entry Name", names(uni), value = TRUE)[1]
oln_col <- grep("ordered locus", names(uni), value = TRUE)[1]
if (is.na(id_col) || is.na(oln_col)) stop("「Entry Name」または「Gene Names (ordered locus)」の列がありません")
id2agi <- tibble(
Accession = uni[id_col](/yoshida1983/protc2026/wiki/id_col),
AGI = str_extract_all(toupper(uni[oln_col](/yoshida1983/protc2026/wiki/oln_col)), "AT[1-5CM]G[0-9]{5}")
) |>
unnest_longer(AGI)
id2agi <- id2agi[!is.na(id2agi$AGI), ] # AGIコードがないエントリを除く
head(id2agi)
- 検出されたタンパク質に、AGIコードを付ける
go_df <- left_join(merged, id2agi, by = "Accession")
# AGIコードに変換できなかったタンパク質
go_df$Accession[is.na(go_df$AGI)]
go_df <- go_df[!is.na(go_df$AGI), ]
dim(go_df) # 複数のAGIコードをもつタンパク質は、複数行になります
サンプルごとのタンパク質リスト
- 奇数番号のサンプルを取り出す(偶数番号は、PCA・クラスタリングで作った
even_samples)
odd_samples <- sample_names[sample_no %% 2 == 1]
odd_samples
even_samples
- サンプルごとに、検出された(Score > 0)タンパク質のAGIコードのリストを作る
gene_lists <- lapply(sample_names, function(s) unique(go_df$AGI[go_df[s](/yoshida1983/protc2026/wiki/s) > 0]))
names(gene_lists) <- sample_names
sapply(gene_lists, length) # サンプルごとのタンパク質の数
GO解析(エンリッチメント解析)
- パッケージの読み込み(初回のみインストール)
- Bioconductorのパッケージは、dplyr の関数(
select()など)と名前がぶつかるので、データの準備を先に済ませてから読み込みます
- Bioconductorのパッケージは、dplyr の関数(
# 初回のみ、先頭の「#」を消して実行(時間がかかります)
# if (!requireNamespace("BiocManager", quietly = TRUE)) install.packages("BiocManager")
# BiocManager::install(c("clusterProfiler", "org.At.tair.db", "ggtangle"))
library(clusterProfiler)
library(org.At.tair.db)
-
library()で「there is no package called '○○'」と出たら、そのパッケージをinstall.packages("○○")でインストールしてから、もう一度library()を実行してください(例:ggtangle) -
サンプルごとに、enrichGOを実行
- 背景(バックグラウンド)は、8サンプルのいずれかで検出された全タンパク質
universe_agi <- unique(go_df$AGI)
length(universe_agi)
ego_list <- lapply(gene_lists, function(g) {
enrichGO(
gene = g,
universe = universe_agi,
OrgDb = org.At.tair.db,
keyType = "TAIR", # AGIコードを使う
ont = "BP", # BP, CC, MF
pAdjustMethod = "BH",
pvalueCutoff = 0.05,
qvalueCutoff = 0.05
)
})
# 1つ目のサンプルの結果を確認
head(as.data.frame(ego_list[1](/yoshida1983/protc2026/wiki/1)))
- エンリッチした GO term(GO ID)を、サンプルごとに取り出す
go_terms <- lapply(ego_list, function(e) {
if (is.null(e)) character(0) else as.data.frame(e)$ID
})
n_terms <- sapply(go_terms, length)
n_terms # サンプルごとの、エンリッチした GO term の数
if (sum(n_terms) == 0) stop("エンリッチした GO term がありませんでした")
奇数・偶数のサンプルの比較
- 奇数番号(異なるタグ由来)と偶数番号(同じライン由来)のセットで、GO term の重なりを数える
- 全サンプル共通:セット内のすべてのサンプルでエンリッチした GO term
- 1サンプルのみ:セット内の1つのサンプルだけでエンリッチした GO term
odd_terms <- go_terms[odd_samples]
even_terms <- go_terms[even_samples]
summarise_terms <- function(term_list) {
all_terms <- unique(unlist(term_list))
n_samples <- sapply(all_terms, function(t) sum(sapply(term_list, function(x) t %in% x)))
data.frame(
"全GO term数" = length(all_terms),
"全サンプル共通" = sum(n_samples == length(term_list)),
"1サンプルのみ" = sum(n_samples == 1),
check.names = FALSE
)
}
rbind(
"奇数(異なるタグ由来)" = summarise_terms(odd_terms),
"偶数(同じライン由来)" = summarise_terms(even_terms)
)
- Venn図で比較
# VennDiagramがログファイルを作らないようにする設定
invisible(futile.logger::flog.threshold(futile.logger::ERROR, name = "VennDiagramLogger"))
venn_odd <- venn.diagram(
x = odd_terms,
filename = NULL,
fill = c("skyblue", "pink1", "mediumorchid", "lightgreen"),
alpha = 0.5,
cex = 1.2,
cat.cex = 1.2,
main = "GO terms: odd-numbered samples"
)
venn_even <- venn.diagram(
x = even_terms,
filename = NULL,
fill = c("skyblue", "pink1", "mediumorchid", "lightgreen"),
alpha = 0.5,
cex = 1.2,
cat.cex = 1.2,
main = "GO terms: even-numbered samples"
)
# 左右に並べて描画
grid.newpage()
pushViewport(viewport(layout = grid.layout(1, 2)))
pushViewport(viewport(layout.pos.row = 1, layout.pos.col = 1))
grid.draw(venn_odd)
popViewport()
pushViewport(viewport(layout.pos.row = 1, layout.pos.col = 2))
grid.draw(venn_even)
popViewport()
popViewport()
サンプルごとの AGIコードを書き出す
for (s in names(gene_lists)) {
writeLines(gene_lists[s](/yoshida1983/protc2026/wiki/s), paste0("shinygo_", s, ".txt"))
}
writeLines(universe_agi, "shinygo_background.txt") # 背景(Background)用
【動作確認用】予備実験サンプル(pre1〜pre5)で行う場合
予備実験のcsv(pre1.csv〜pre5.csv)で、GO解析(サンプルごとのエンリッチメント解析と、GO term の比較)までを、まとめて確認するためのコードです。
- PCA・クラスタリングの【動作確認用】のコードを、同じプロジェクトで実行して、
merged_preとnames_preを作ったあとに、実行してください - 対応表(
uniprotkb_...tsv)も、同じプロジェクトのフォルダに置いてください - pre1〜pre5 の5サンプルを、まとめて比べます(奇数・偶数には分けません)
# ---- 対応表の読み込み(Accession → AGIコード)----
uni_file <- list.files(pattern = "^uniprotkb_.*\\.tsv(\\.gz)?$")
if (length(uni_file) != 1) stop("対応表のファイルが1つではありません。Filesを確認してください")
uni <- read_tsv(uni_file, show_col_types = FALSE)
id_col <- grep("Entry Name", names(uni), value = TRUE)[1]
oln_col <- grep("ordered locus", names(uni), value = TRUE)[1]
if (is.na(id_col) || is.na(oln_col)) stop("「Entry Name」または「Gene Names (ordered locus)」の列がありません")
id2agi <- tibble(
Accession = uni[id_col](/yoshida1983/protc2026/wiki/id_col),
AGI = str_extract_all(toupper(uni[oln_col](/yoshida1983/protc2026/wiki/oln_col)), "AT[1-5CM]G[0-9]{5}")
) |>
unnest_longer(AGI)
id2agi <- id2agi[!is.na(id2agi$AGI), ]
go_pre <- left_join(merged_pre, id2agi, by = "Accession")
go_pre$Accession[is.na(go_pre$AGI)] # AGIコードに変換できなかったタンパク質
go_pre <- go_pre[!is.na(go_pre$AGI), ]
dim(go_pre)
# ---- サンプルごとのタンパク質リスト ----
gene_pre <- lapply(names_pre, function(s) unique(go_pre$AGI[go_pre[s](/yoshida1983/protc2026/wiki/s) > 0]))
names(gene_pre) <- names_pre
sapply(gene_pre, length) # サンプルごとのタンパク質の数
# ---- GO解析(エンリッチメント解析)----
library(clusterProfiler)
library(org.At.tair.db)
# 背景:pre1〜pre5 のいずれかで検出された全タンパク質
universe_pre <- unique(go_pre$AGI)
length(universe_pre)
ego_pre <- lapply(gene_pre, function(g) {
enrichGO(
gene = g,
universe = universe_pre,
OrgDb = org.At.tair.db,
keyType = "TAIR",
ont = "BP",
pAdjustMethod = "BH",
pvalueCutoff = 0.05,
qvalueCutoff = 0.05
)
})
head(as.data.frame(ego_pre[1](/yoshida1983/protc2026/wiki/1))) # 1つ目のサンプルの結果を確認
terms_pre <- lapply(ego_pre, function(e) {
if (is.null(e)) character(0) else as.data.frame(e)$ID
})
n_pre <- sapply(terms_pre, length)
n_pre # サンプルごとの、エンリッチした GO term の数
if (sum(n_pre) == 0) stop("エンリッチした GO term がありませんでした")
# ---- GO term の重なり ----
all_terms <- unique(unlist(terms_pre))
n_samples <- sapply(all_terms, function(t) sum(sapply(terms_pre, function(x) t %in% x)))
data.frame(
"全GO term数" = length(all_terms),
"全サンプル共通" = sum(n_samples == length(terms_pre)),
"1サンプルのみ" = sum(n_samples == 1),
check.names = FALSE
)
# Venn図(5サンプル)
invisible(futile.logger::flog.threshold(futile.logger::ERROR, name = "VennDiagramLogger"))
venn_pre_go <- venn.diagram(
x = terms_pre,
filename = NULL,
fill = c("skyblue", "pink1", "mediumorchid", "lightgreen", "orange"),
alpha = 0.5,
cex = 1.2,
cat.cex = 1.2,
main = "GO terms: pre samples"
)
grid.newpage()
grid.draw(venn_pre_go)