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関数を使うと同じ型のデータを集約していくことが簡単にできます。