以下で説明する(自明ではない)問題について説明しました。これは私の最初の投稿で、現在は修正版です。入力または提案された解決策は役に立ちます。
これにはいくつかの側面があります:小規模な問題の最適解の決定(既に以下にいくつかの提案があります)、時間(以下の data.table ソリューションはボックスをチェックしているようです)、およびメモリ管理です。問題は、あるテーブルで列挙され、別のテーブルのクラスターによって表されるタグに関するものです (同じストランドで 30bp 以内の場合は同じクラスター)。
課題は、特定のタグを適切な間隔に割り当てる効率的な手順を決定することです。つまり、タグ座標は開始位置、終了位置 (= 開始位置 + 1)、染色体 (完全なデータセットで 25 の値)、および鎖 (位置はプラス鎖またはマイナス鎖のいずれかにある) によって決定されます。二本鎖DNA)。したがって、クラスターは同じストランド上でオーバーラップしませんが、クラスターの間隔が異なるストランド上にある場合、クラスター座標がオーバーラップする可能性があり、事態が複雑になります。
これは 1 月 9 日の私の投稿の修正版であり、問題の本質的な難しさをよりよくカプセル化しています。小規模な問題を解決する高速なソリューションを後で示します。誰かが完全なデータセットで作業したい場合は、私に知らせてください. よろしくお願いします!
よろしく、
ニック・クラーク
背景 この問題には、グループごとの間隔と最大 n が含まれます。クラスター化された遺伝子座標 (クラスター) と入力データ (タグ) を含む 2 つのテーブルがあります。クラスタ テーブルには、タグ テーブルからの同じストランドでカバーされた各重複しない間隔から合計されたタグが含まれます。完全なクラスター テーブルには 160 万行あります。タグ テーブルは約 400 万行なので、ソリューションは理想的にはベクトル化する必要があります。サンプルデータについては、以下を参照してください。設定は、ヒトの転写開始点(CAGE)に関するデータセットです。
私は R で作業しているので、R または SQL に基づくソリューションを探しています。Rのplyrパッケージとsqldfパッケージの両方を使用して、以前に失敗した試みを行いました.
課題 私が見逃しているのは、クラスター化されたテーブル内の行で、最大のタグの貢献度に関連付けられた入力データ テーブルから開始座標を特定することです。
1) 異なるストランドからのクラスターは重複する座標を持つことができる、2) chr / chr_clst は 25 の異なる値を取ることができる (例には示されていません)、3) ソリューションはストランドと chr / chr_clst の両方を考慮する必要があることに注意してください。
私の理想的な解決策: ベクトル化された R コードまたは以下の SQL ステートメントの改善。メモリの問題を説明する以下のソリューションのバージョンは、うまくいくでしょう。クラスタ テーブルから適切な行を効率的に決定する改善された SQL ステートメントと同様です。
これまでの状況 これ は、これまでのところ明らかに最良の解決策です。コードについては user1935457 を、その後の修正案については mnel を参照してください。ここでの問題は、おもちゃの例からフル スケール テーブルに移動すると、メモリに対する過剰な要求が原因で R (および R Studio) の両方がクラッシュすることです。
# Convert sample data provided in question
clusters <- as.data.table(clusters)
tags <- as.data.table(tags)
# Rename chr and strand for easier joining
setnames(clusters, c("chr_clst", "strand_clst"), c("chr", "strand"))
# Set key on each table for next step
setkey(clusters, chr, strand)
setkey(tags, chr, strand)
# Merge on the keys
tmp <- merge(clusters, tags, by = c("chr", "strand"))
# Find index (in merged table, tmp) of largest tag_count in each
# group subject to start_clst <= end <= end_clst
idx <- tmp[between(end, start_clst, end_clst),
list(IDX=.I[which.max(tag_count)]),
by=list(chr, start_clst,end_clst,strand)]$IDX
# Get those rows from merged table
tmp[idx]
最初に、R の sqldf パッケージを使用して基本的な SQL クエリを作成しました (このバージョンでは、最大値に関連付けられた座標ではなく、最大値が検出されます)。両方のテーブルに (できれば) 適切なインデックスを配置しているにもかかわらず、クエリの実行には永遠に時間がかかります。
output_tablename <- sqldf(c(
"create index ai1 on clusters(chr_clst, start_clst, end_clst, strand_clst)",
"create index ai2 on tags(chr, start, end, strand)",
"select a.chr_clst, a.start_clst, a.end_clst, a.strand_clst, sum(b.tags)
from main.clusters a
inner join main.tags b on a.chr_clst=b.chr and a.strand_clst = b.strand
and b.end between a.start_clst and a.end_clst
group by a.chr_clst, a.start_clst, a.end_clst, a.strand_clst
order by a.chr_clst, a.start_clst, a.end_clst, a.strand_clst"
))
テーブル構造
クラスター: chr_clst、start_clst、end_clst、strand_clst、tags_clst。
タグ: chr、start、end、strand、tag_count。
R 形式のサンプル データ 完全なデータセットで作業したい人がいたら教えてください。
クラスター:
chr_clst <- c("chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1")
start_clst <- c(568911, 569233, 569454, 569793, 569877, 569926, 569972, 570048, 570166, 713987)
end_clst <- c(568941, 569256, 569484, 569803, 569926, 569952, 569973, 570095, 570167, 714049)
strand_clst <- c("+", "+", "+", "+", "+", "-", "+", "+", "+", "-")
tags_clst <- c(37, 4, 6, 3, 80, 25, 1, 4, 1, 46)
clusters <- data.frame(cbind(chr_clst, start_clst, end_clst, strand_clst, tags_clst))
clusters$start_clst <- as.numeric(as.character(clusters$start_clst))
clusters$end_clst <- as.numeric(as.character(clusters$end_clst))
clusters$tags_clst <- as.numeric(as.character(clusters$tags_clst))
rm(chr_clst, start_clst, end_clst, start_clst, strand_clst, tags_clst)
タグ:
chr <- c("chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1",
"chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1",
"chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1",
"chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1",
"chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1",
"chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1",
"chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1",
"chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1",
"chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1",
"chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1",
"chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1",
"chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1",
"chr1")
start <- c(568911, 568912, 568913, 568913, 568914, 568916, 568917, 568918, 568929,
568929, 568932, 568933, 568935, 568937, 568939, 568940, 568940, 569233, 569247,
569255, 569454, 569469, 569471, 569475, 569483, 569793, 569802, 569877, 569880,
569887, 569889, 569890, 569891, 569893, 569894, 569895, 569895, 569896, 569897,
569898, 569898, 569899, 569900, 569900, 569901, 569901, 569903, 569905, 569906,
569907, 569907, 569908, 569908, 569909, 569910, 569910, 569911, 569911, 569912,
569914, 569914, 569915, 569916, 569917, 569918, 569919, 569920, 569920, 569925,
569926, 569936, 569938, 569939, 569939, 569940, 569941, 569941, 569942, 569942,
569943, 569944, 569948, 569948, 569951, 569972, 570048, 570057, 570078, 570094,
570166, 713987, 713989, 713995, 714001, 714001, 714007, 714008, 714010, 714011,
714011, 714011, 714013, 714015, 714015, 714017, 714018, 714019, 714023, 714025,
714029, 714034, 714034, 714037, 714038, 714039, 714039, 714040, 714042, 714048,
714048)
end <- c(568912, 568913, 568914, 568914, 568915, 568917, 568918, 568919, 568930,
568930, 568933, 568934, 568936, 568938, 568940, 568941, 568941, 569234, 569248,
569256, 569455, 569470, 569472, 569476, 569484, 569794, 569803, 569878, 569881,
569888, 569890, 569891, 569892, 569894, 569895, 569896, 569896, 569897, 569898,
569899, 569899, 569900, 569901, 569901, 569902, 569902, 569904, 569906, 569907,
569908, 569908, 569909, 569909, 569910, 569911, 569911, 569912, 569912, 569913,
569915, 569915, 569916, 569917, 569918, 569919, 569920, 569921, 569921, 569926,
569927, 569937, 569939, 569940, 569940, 569941, 569942, 569942, 569943, 569943,
569944, 569945, 569949, 569949, 569952, 569973, 570049, 570058, 570079, 570095,
570167, 713988, 713990, 713996, 714002, 714002, 714008, 714009, 714011, 714012,
714012, 714012, 714014, 714016, 714016, 714018, 714019, 714020, 714024, 714026,
714030, 714035, 714035, 714038, 714039, 714040, 714040, 714041, 714043, 714049,
714049)
strand <- c("+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+",
"+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+",
"+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+",
"+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+",
"+", "+", "+", "+", "+", "+", "+", "+", "-", "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "-", "-", "+", "+", "+", "+", "+", "+", "-", "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-")
tag_count <- c(1, 1, 1, 2, 3, 2, 3, 1, 1, 1, 1, 1, 2, 1, 6, 2, 8, 1, 1, 2, 1, 1, 2,
1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 4, 4, 1, 1, 1, 1, 1, 3, 2, 1, 1, 2, 4, 2, 4, 2, 4,
1, 1, 1, 1, 3, 2, 1, 3, 1, 2, 3, 1, 1, 3, 2, 1, 1, 1, 5, 1, 2, 1, 2, 1, 1, 2, 2,
4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 3, 2, 4, 2, 1, 1, 1,
2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 1, 2)
tags <- data.frame(cbind(chr, start, end, strand, tag_count))
tags$start <- as.numeric(as.character(tags$start))
tags$end <- as.numeric(as.character(tags$end))
tags$tag_count <- as.numeric(as.character(tags$tag_count))
rm(chr, start, end, strand, tag_count)