2018年9月27日木曜日

相関行列からネットワークへ

 (昨日の記事から色々追加・修正したので、新しく書き直しました。)
 FisherのZ変換を施された相関行列でネットワーク解析を行う。

お品書き
1. FisherのZ変換の逆作業をして生の相関行列を作る
2. 有意な相関係数のみ残す
3. 相関行列からsemi-metricな距離行列を作成する
4. semi-metricな距離行列から重み付き隣接行列を作成する

1. FisherのZ変換の逆作業をして生の相関行列を作る
 某解析ソフトは相関行列を計算した結果にFisherのZ変換を施すために値が[-1, 1]から溢れる。邪魔くさいので元の相関係数に戻したい。
 入力のcsvファイルを逆関数にぶちこむだけのシンプルなもの。

--------------------------------------------------
#Usage
#python3 matrix_Z2R.py [input filename] [output filename]
#
#Input
#[input filename]: csv file (correlation coefficient matrix converted Z-score by Fisher's method)
#[output filename]: output filename
#
#Output
#[output filename]: raw correlation coefficient matrix

import sys
import numpy as np

filename=sys.argv[1]
output=sys.argv[2]

matrix=np.loadtxt(filename, delimiter=',')
matrix=(np.exp(2*matrix)-1)/(np.exp(2*matrix)+1)

np.savetxt(output, matrix, delimiter=',')
--------------------------------------------------


2. 有意な相関係数のみ残す
 プログラムどうこうというより、無相関検定の復習になった。

--------------------------------------------------
#Usage
#python3 Rmat_significant.py [input filename] [output filename] [number of sample] [significance level]
#
#Input
#[input filename]: Input csv filename (correlation coefficient matrix)
#[output filename]: Output csv filename
#[number of sample]: Number of samples to calculate each correlation coefficient
#[significance level]: significance level (usually 0.05)
#
#Output
#[output filename]: adjacency matrix filled with 0 or 1

import sys
import numpy as np
import scipy.stats

filename=sys.argv[1]
output_filename=sys.argv[2]
n_sample=np.int(sys.argv[3])
alpha=np.float(sys.argv[4])

#load inputfile
matrix=np.loadtxt(filename, delimiter=',')
matrix[np.isnan(matrix)]=0

#get T-value matrix by correlation coefficient matrix
Tmat=np.abs(matrix)*pow(n_sample-2, 1/2)/((1-matrix**2)**(1/2))

#get T threshold for significance
T_sig=-1*scipy.stats.t.ppf(q=[alpha/2], df=n_sample-2)

#set unsignificant values 0
matrix[Tmat<T_sig]=0

#set minus R 0
matrix[matrix<0]=0

#Output
np.savetxt(output_filename, matrix, delimiter=',')
--------------------------------------------------


3. 相関行列からsemi-metricな距離行列を作成する
 話が前後するのだが、4で距離を重みにするときに単に「距離の逆数を重みとする」のではなく、「距離に1を足した数の逆数を重みとする」のが個人的にすごいグッときたんすよね。以前遊んでいた時に、ゼロの逆数が無限大になるのがとても扱いにくかったので、なるほどなぁと。
 そんなわけで距離行列作成では「重み(相関係数)の逆数から1を引く」作業をしている。

--------------------------------------------------
#Usage
#python3 tnorm_r2len.py [input filename] [output filename]
#Input
#
#[input filename]: input weighted matrix csv filename
#[output filename]: output filename
#
#Output
#
#[output filename]: t-norm length matrix

import sys
import numpy as np
inf=np.inf

input_filename=sys.argv[1]
output_filename=sys.argv[2]

matrix=np.loadtxt(input_filename, delimiter=',')

matrix[matrix==0]=inf
matrix=matrix**(-1)
matrix-=1
matrix[matrix<0]=inf

np.savetxt(output_filename, matrix, delimiter=',')
--------------------------------------------------

4. semi-metricな距離行列から重み付き隣接行列を作成する
 現時点では有意とならない相関となったノード間には結合が存在しないが、結合が存在しないノード間にも重みを見出したいとする。そこで、距離行列からダイクストラ法でノード間の最短距離を求め、Dombi t-normで変換したものを重みとしているものがあって、なるほどなぁと思いそれを採用。なお対角成分はゼロにセットしなおすので、2分グラフは未対応。

--------------------------------------------------
#Usage
#python3 tnorm_len2wei.py [input filename] [output filename]
#
#Input
#[input filename]: length matrix csv file
#[output filename]: save weighted matrix as the argv

import sys
import numpy as np
import networktools

input_filename=sys.argv[1]
output_filename=sys.argv[2]

matrix=np.loadtxt(input_filename, delimiter=',')

matrix=networktools.shortest_path_length(matrix)
matrix=(matrix+1)**(-1)

for i in range(matrix.shape[0]):
 matrix[i, i]=0

np.savetxt(output_filename, matrix, delimiter=',')
--------------------------------------------------

 そんなわけで上4つを順に呼べば、某ソフトで出力される相関行列からネットワークの距離行列と重み付き隣接行列を作成することができるようになった。

PS
 久々に文字サイズがそろわない。大量のHTMLが突っ込まれているのはわかるんだが、どの作業の時に突っ込まれるのか全くわからん…

0 件のコメント:

コメントを投稿