x(n), y(n) のデータからシンプルに、それぞれの平均と標準偏差、
相関係数を求めるサブルーチン。
ついでに、線形回帰も
テストのための主プログラムとして、1000行までの x y の値を書いた
テキストファイルを標準入力から読み込むものをとりあえずつけてある。
implicit none integer, parameter :: num=1000 real :: x(num), y(num) integer :: i, j, n real :: xm, ym, sigx, sigy, cor real :: a, b i=1 do while( 1==1 ) read(*,*, END=900) x(i), y(i) i=i+1 if(i>num) then write(0,*) 'too many data. Change num' stop end if end do 900 n=i-1 do i=1, n write(0,*) i, x(i), y(i) end do call correlation(x, y, n, xm, ym, sigx, sigy, cor) write(*,*) 'Mean x = ', xm, 'Sig x =', sigx write(*,*) 'Mean y = ', ym, 'Sig y =', sigy write(*,*) 'Correlation = ', cor call calc_ab( x, y, n, a, b) write(*,*) 'y=ax+b', 'a=', a, 'b=', b end subroutine correlation(x, y, n, xm, ym, sigx, sigy, cor) implicit none integer :: n, i real :: x(n), y(n) real :: xm, ym, sigx, sigy, cor real(kind=8) :: sx, sy, sxy, sx2, sy2 sx=0; sy=0; sxy=0; sx2=0; sy2=0 if( n > 2 ) then do i=1, n sx = sx +x(i) sy = sy +y(i) end do xm = sx/n; ym = sy/n do i=1, n sx2 = sx2 + (x(i)-xm)*(x(i)-xm) sy2 = sy2 + (y(i)-ym)*(y(i)-ym) sxy = sxy + (x(i)-xm)*(y(i)-ym) end do sigx = sqrt(sx2/n); sigy = sqrt(sy2/n) if( sigx > 0 .AND. sigy > 0 ) then cor = (sxy/n)/(sigx*sigy) end if end if end subroutine calc_ab( x, y, n, a, b) ! y = ax+b implicit none integer :: n, i real :: x(n), y(n), a, b double precision :: sx2, sx, sxy, sy, d sx2 = 0 ; sx = 0 ; sxy = 0; sy = 0 do i=1,n sx2 = sx2 + x(i)*x(i) ! sx2 = sx2 + i*i sx = sx + x(i) ! sx = sx + i sxy = sxy + x(i)*y(i) !sxy = sxy + i*x(i) sy = sy + y(i) !sy = sy + x(i) end do d = sx2 * n - sx * sx a = (n*sxy-sx*sy)/d b = (-sx*sxy+sx2*sy)/d end
玉川 2011.12.1