import numpy as np
import scipy.signal as signal
import sys
from tools import unshape
NA = np.newaxis
def runave(rdata, length):
"""runnnig average
Arguments:
'array' -- first dimension must be time.
'length' -- runnning mean length
"""
ntim = rdata.shape[0]
if ntim < length:
print "input array first dimension length must be larger than length."
sys.exit()
if rdata.ndim == 1:
if length%2 != 0:
w = np.ones(length)/float(length)
else:
w = np.r_[0.5, np.ones(length-1), 0.5]/float(length)
runarray = np.ma.array(signal.convolve(rdata, w, 'same'))
runarray[:length/2] = np.ma.masked
runarray[-length/2:] = np.ma.masked
elif rdata.ndim == 2:
if length%2 != 0:
w = np.vstack((np.zeros(length),np.ones(length),np.zeros(length)))/float(length)
else:
w = np.vstack((np.zeros(length+1),np.r_[0.5, np.ones(length-1), 0.5],\
np.zeros(length+1)))/float(length)
runarray = np.ma.array(signal.convolve2d(rdata, w, 'same'))
runarray[:length/2,:] = np.ma.masked
runarray[-length/2:,:] = np.ma.masked
else :
rdata, oldshape = unshape(rdata)
if length%2 != 0:
w = np.vstack((np.zeros(length),np.ones(length),np.zeros(length)))/float(length)
else:
w = np.vstack((np.zeros(length+1),np.r_[0.5, np.ones(length-1), 0.5],\
np.zeros(length+1)))/float(length)
runarray = np.ma.array(signal.convolve2d(rdata, w, 'same'))
runarray[:length/2,:] = np.ma.masked
runarray[-length/2:,:] = np.ma.masked
runarray = runarray.reshape(oldshape)
return runarray
ベクトル同士の線形回帰ならnumpy.linalg.lstsq や scipy.stats.linregress がよい。同じ時系列をもつ多次元配列をまとめて線形回帰するにはnumpy.polyfitが使える。
def regression(x, y):
"""
regression y = ax + b
"""
if x.ndim != 1:
print "error x must be 1-D array"
sys.exit()
if y.ndim >= 2:
y, oldshape = unshape(y)
p = np.polyfit(x,y,1)
a = p[0].reshape(oldshape[1:])
b = p[1].reshape(oldshape[1:])
else:
p = np.polyfit(x,y,1)
a = p[0]
b = p[1]
return a, b
データ行列を特異値分解することにより求める。数学的な原理はこちらを参考。こんな感じになるか(要確認)。
import numpy
import scipy.linalg
import math
NA = numpy.newaxis
PI = 4.*math.atan(1.)
#経度144、緯度37、時間31のGrADS形式のバイナリを例に
f = open("ファイルパス","rb")
data = numpy.fromfile(f, "<f").reshape(31,37,144)
f.close()
#31年平均を気候値として偏差を求める
residual = data - data.mean(axis=0)
#緯度に応じた面積重みをつける
lat = numpy.arange(0., 91., 2.5)
input = residual*numpy.sqrt(numpy.cos(2.0*PI/360.0*lat))[NA,:,NA]
input = input.reshape(31,37*144)
#特異値分解
A, Lh, E = scipy.linalg.svd(input, full_matrices=False)
#固有値が並んだ配列
lambdas = Lh*Lh/(len(residual)-1)
#固有ベクトル[w1, w2, ... ]
EOFs = numpy.transpose(E)
#PC
PCs = A*Lh
#再規格化する場合
EOFs = EOFs * numpy.sqrt(lambdas)[NA,:]
PCs = PCs / numpy.sqrt(lambdas)[NA,:]
#緯度重みを考慮
EOFs = EOFs.reshape(37,144,len(lambdas)) / numpy.sqrt(numpy.cos(2.0*PI/360.0*lat))[NA,:,NA]
#寄与率
explained = lambdas / numpy.add.reduce(lambdas)
#第mモードのEOF、PC、寄与率はEOFs[:,:,m], PCs[:,m]、explained[m]になる(はず)
分散共分散行列の固有値問題を用いる場合は以下のような感じになるか。SVDを用いる方が早い気がする。

最新コメント