2017-07-06 16 views
0

我有一個程序來讀取和分層多元正態總體與(x,y)值的R文件。我想將人口分成兩組,其中分部是基於如果x和y高於或低於特定數字。劃分人口Fortran - 接收零

當我做Fortran進行分層,我沒有得到任何結果,但零x和y,這樣的事情

total number of individuals  1551 
    0.00000000  0.00000000   
    0.00000000  0.00000000   
    0.00000000  0.00000000   
    0.00000000  0.00000000   
    0.00000000  0.00000000   
    0.00000000  0.00000000   
    0.00000000  0.00000000   
    0.00000000  0.00000000   
    0.00000000  0.00000000   
    0.00000000  0.00000000   

. 
. 
. 

原始數據看起來像這樣

755,885 
656,841 
742,844 
747,829 
776,861 
696,809 
782,891 
771,867 
760,826 
812,830 
711,792 
736,840 
738,873 
793,833 
751,836 
747,871 
796,830 
711,868 
747,843 
758,835 
760,824 
759,839 
696,868 

I have attached the file to the original data from R as well

program test 


implicit none 

    real, dimension(:), allocatable :: x,y 
    real, dimension(:,:), allocatable :: s1, s2, s3, s4 
    integer:: io, l1, l2, l3,l4,n,i 

    open(33, file = '', status = 'old', action = 'read') 
    n = 0 
    DO 
     READ(33,*,iostat=io) 
     IF (io/=0) EXIT 
     n = n + 1 
    END DO 

    allocate(x(n) ,y(n)) 
    rewind(33) 

    DO i =1,n 
     READ(33,*) x(i), y(i) 
    END DO 

    allocate(s1(n,2)) 
    allocate(s2(n,2)) 
    allocate(s3(n,2)) 
    allocate(s4(n,2)) 

    s1=0 
    s2=0 
    s3=0 
    s4=0 

    l1=1 
    l2=1 
    l3=1 
    l4=1 

    do i = 1 , n 
     if (x(i) >=0 .AND. x(i)<=500) then 
      if(y(i) >= 0 .AND. y(i) <=500) then 
       s1(l1, :)=(/x(i), y(i) /) 
       l1=l1+1 
      end if 

     else if (x(i) > 500 .AND. x(i) <= 1000) then 
      if (y(i) > 0 .AND. y(i) < 500) then 
       s2(l2, :)=(/x(i), y(i) /) 
       l2=l2+1 
      end if 
     end if 

     write(*,*) s1(l1, :) 
    end do !iloop 

end program test 

我不知道我在這裏做什麼錯。

+0

它是數據中的逗號 - 將其更改爲空格 – cup

+0

歡迎。一定要去[巡迴]。針對所有Fortran問題使用標籤[tag:fortran]。如果您的問題是版本特定的,您可以爲特定版本添加標籤。但是你的問題不是特定於版本的。 –

+0

你的程序很難閱讀。當你的代碼應該被別人查看時,請使用一致的行縮進。它會幫助你更好地看到結構。 –

回答

0

這被稱爲「懸掛ELSE問題」。 FORTRAN認爲「else if(x(i)> 500 ...」部分屬於「if(y(i)> = 0 .AND。y(i)< = 500)」語句。 IF」前的‘其他’。

do i = 1 , n 
    if (x(i) >=0 .AND. x(i)<=500) THEN 
     if(y(i) >= 0 .AND. y(i) <=500) THEN 
      s1(l1, :)=(/x(i), y(i) /) 
       l1=l1+1 
     end if 
    else if (x(i) > 500 .AND. x(i) <= 1000)THEN 
     if (y(i) > 0 .AND. y(i) < 500) THEN 
      s2(l2, :)=(/x(i), y(i) /) 
       l2=l2+1 
     END IF 
    END IF 
END do !iloop 
+0

@francescalus,對不起,你真的是什麼意思?該問題已經具有x和y的值以及以文本格式指向實際數據文件的鏈接。 – Due

+0

@Rainer非常感謝。我已經嘗試了你的想法,但我仍然面臨同樣的問題。輸出爲零且沒有值。 – Due

+0

@francescalus你是對的。非常感謝你指出這一點。似乎我忘了在編輯代碼時將其添加到此處。現在,代碼是通過初始化{x}和{y}} – Due

0

鑑於數據文件,你所提供的例子,我覺得你得到的輸出是正確的。每個案例落入X> 500,Y> 500,和你的代碼不支持將這些條目寫入分層結構

據我所知,下面是對原始問題的一個解決方案,我已將代碼分解爲多個子例程,這有助於更容易理解請注意,我的代碼中的假設是所有數據都在0 - 1000範圍內。

module util 
    implicit none 
    private 

    public :: get_strat 
    public :: write_strat 

    contains 
     function get_strat(x, y) result(strat) 
      integer, intent(in) :: x 
      integer, intent(in) :: y 
      integer :: strat 

      integer, parameter :: mid_val = 500 

      if (x < mid_val .and. y < mid_val) then 
       strat = 1 
      else if (x < mid_val .and. y >= mid_val) then 
       strat = 2 
      else if (x > mid_val .and. y < mid_val) then 
       strat = 3 
      else 
       strat = 4 
      end if 

     end function 

     subroutine write_strat(trg, strat, x, y) 
      integer, intent(in) :: trg 
      integer, intent(in) :: strat(:) 
      integer, intent(in) :: x(:) 
      integer, intent(in) :: y(:) 

      integer :: i, count_strat 

      count_strat = 0 

      write(*, *) "Writing stratification ", trg 
      do i = 1, size(x) 
       if (strat(i) == trg) then 
        write(*, *) x(i), y(i) 
        count_strat = count_strat + 1 
       end if 
      end do 
      write(*, *) "Total = ", count_strat 
      write(*, *) 
     end subroutine 
end module util 

program test 
    use util 
    implicit none 

    integer, dimension(:), allocatable :: x,y, strat 
    integer:: io, n, i 

    open(33, file = 'xyBVNData_R.txt', status = 'old', action = 'read') 
    n = 0 

    do 
     read(33, *, iostat=io) 
     if(io /= 0) exit 
     n = n + 1 
    end do 

    allocate(x(n) ,y(n), strat(n)) 
    rewind(33) 

    do i = 1, n 
     read(33, *) x(i), y(i) 
    end do 

    do i = 1, n 
     strat(i) = get_strat(x(i), y(i)) 
    end do 

    do i = 1, 4 
     call write_strat(i, strat, x, y) 
    end do 

end program test 

通過分解這樣的代碼,它變得更容易理解和發現任何邏輯缺陷。例如,在您的代碼中,查找匹配後,計數變量l1 ...的增量行。這意味着在程序結束時,計數比匹配條目的數量大1。更清晰的成語將是:

l# = 0 
... 
if (...logic...) 
    l# = l# + 1 
    !! Do something 
end if 
+0

非常感謝您的努力。我還沒有嘗試過代碼,因爲我對Fortran非常重要,在將它應用於我的數據之前,我需要首先了解您的代碼。然而,無論如何,在你的知識幫助他人方面,你應該得到一個巨大的謝意。 – Due

+0

@Due沒問題。如果您是使用Fortran的初學者,可能需要考慮是否使用正確的語言來完成這項工作。 (假設我的解決方案如上所述),這絕對是可能的,但只需要幾行Python或Perl就可以達到同樣的效果。我希望它能更容易理解這些語言正在發生什麼。 – s8129