Rでデータ連結
次のようなデータがあって、同じ遺伝子(1列目)のデータを連結したい(横に並べたい)とします。
1つ目のデータ
logCPM logFC PValue FDR AT5G07990.1 6.502 -0.955 2.55E-13 9.32E-09 AT5G48880.1 7.027 -0.567 1.18E-11 2.15E-07 AT5G48880.3 6.990 -0.545 7.42E-11 9.03E-07 AT5G48880.2 7.020 -0.537 1.26E-10 1.15E-06 (以下数万行)
2つ目のデータ
logCPM logFC PValue FDR AT5G58240.1 4.668 -1.552 3.34E-30 1.22E-25 AT5G58240.2 4.415 -1.406 2.56E-20 4.68E-16 AT5G22650.1 7.769 -0.926 1.66E-15 1.83E-11 AT5G22650.2 7.705 -0.925 2.00E-15 1.83E-11 (以下数万行)
1列目の並び順が異なるだけの場合
データの列名をrownamesで取り出して、それの並び順をorderでつくります。d1[order(rownames(d1)),]とすることで、1列目の順に並べます。2つ目のデータも同じように並べ替えて、cbindで連結します。
> d1 <- read.table("data1.txt") > d2 <- read.table("data2.txt") > cbind(d1[order(rownames(d1)),], d2[order(rownames(d2)),]) logCPM logFC PValue FDR logCPM logFC PValue FDR AT1G01010.1 4.849 -0.290 0.077 0.499 4.849 -0.109 0.509 1.000 AT1G01020.1 4.446 -0.098 0.553 0.751 4.446 0.118 0.459 1.000 AT1G01020.2 4.154 -0.109 0.559 0.755 4.154 0.094 0.619 1.000 AT1G01030.1 4.926 -0.264 0.104 0.514 4.926 -0.040 0.809 1.000 (以下数万行)
行数が異なる場合
上の例のように行数が同じ場合でもmerge関数を使えば、コードもより簡単になります。どの列の値で連結するかをbyに与えます。今回は列名なので0です。どちらかに欠損値がある場合は、allをつけておくと行数が減りません。
> merge(d1, d2, by = 0) Row.names logCPM.x logFC.x PValue.x FDR.x logCPM.y logFC.y PValue.y FDR.y 1 AT1G01010.1 4.849 -0.290 0.077 0.499 4.849 -0.109 0.509 1 2 AT1G01020.1 4.446 -0.098 0.553 0.751 4.446 0.118 0.459 1 3 AT1G01020.2 4.154 -0.109 0.559 0.755 4.154 0.094 0.619 1 4 AT1G01030.1 4.926 -0.264 0.104 0.514 4.926 -0.040 0.809 1 (以下数万行)
2つのファイルなら上記で済みますが、3つ4つと増えていくとコードを書いていくのが大変です。そこで、繰り返しなどを使って楽をしようと思うのですが、最初の処理だけ別になって面倒になります。
一つ目だけ別の処理をしているあまり面白くないコード
files <- list.files(path = ".", pattern = "*.txt", full.names = TRUE) for(file in files){ buf <- read.table(file) if(file == files[1]){ d <- buf }else{ d <- merge(d, buf, by = 0) # mergeすると行についた名前が1列目になってしまうので、これを行名に戻す rownames(d) <- d[,1] d <- d[, -1] } }
if(file == files[1]) として、1つ目のデータだけ別の処理をしています。いまいち格好よくありません。
イケてると思うコード
data <- lapply(files, read.table) d <- Reduce(function (d1, d2){ d <- merge(d1, d2, by = 0) rownames(d) <- d[,1] d[, -1] }, data)
Reduce関数を使うと同じ型のデータを集約していくことが簡単にできます。