2017-07-06 15 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