0

This is a follow-up question from Fortran: Open, form='(un)formatted', read. I have to create an array that saves the number of elements under certain criteria.

program location
implicit none
interface
    function distkm(deglat1,deglon1,deglat2,deglon2)
    real :: distkm
    real, intent(in) :: deglat1,deglon1,deglat2,deglon2
    end function distkm
end interface
integer, parameter :: maxnr = 200000
integer :: nr, i, j, ios
character(len=1) :: junkfornr
real :: start, finish
! My variable declaration
character(len=15), dimension(:), allocatable :: key
real, dimension(:), allocatable :: lat, lon
integer, dimension(:), allocatable :: jobs
! Secondary arrays
integer, dimension(:), allocatable :: jobs_within
    integer, dimension(:), allocatable :: sum_jobs
! Determine total number of lines in file
nr=0
open(10, file='location_data2.txt', status='old')
do i=1,maxnr
    read(10,*,iostat=ios) junkfornr
    if (ios/=0) exit
    if (i == maxnr) then
        stop
    endif
    nr = nr + 1
end do
! Create variables: key, lat, lon, jobs
allocate(key(nr))
allocate(lat(nr))
allocate(lon(nr))
allocate(jobs(nr))
allocate(jobs_within(nr))
allocate(sum_jobs(nr))
rewind(10)
do i=1,nr
    read(10,*) key(i), lat(i), lon(i), jobs(i)
end do
do i=1,nr
    do j=1,nr
        if (distkm(lat(i),lon(i),lat(j),lon(j)) <= 0.3) then
            jobs_within(j) = jobs(j)
        else
            jobs_within(j) = 0
        end if  
    end do
    sum_jobs(i) = sum(jobs_within)
end do
close(10)
open(20,file='key_sum_jobs_0.3.txt')
do i=1,nr
    write(20,100) key(i), sum_jobs(i)
end do
100 format(A15,I6)
end program location

The do loops save the sum of workers within 0.3 kilometers for each firm. Here, for each firm, the number of firms within 0.3 kilometers varies. How can I create an array (say, n_neighbor) that records the number of adjacent firms for each firm?

EDIT: I believe the following solves the problem:

do i=1,nr
    n_aux(1:nr) = 0
    do j=1,nr
        if (distkm(lat(i),lon(i),lat(j),lon(j)) <= 1) then
            jobs_within(j) = jobs(j)
            n_aux(j) = n_aux(j) + 1
        else
            jobs_within(j) = 0
        end if
    end do
    write(20,100) key(i), sum(jobs_within), sum(n_aux)
    100 format(A15,I8,1X,I3)
end do

I create an integer array (n_aux). Then, the output text file of unit=20 saves three columns: (1) firm key, (2) sum of workers within 0.3km, and (3) the number of firms within 0.3km.

Things to ponder: I set all the elements of n_aux be 0 ahead of the j loop. Then, I throw 1's where the if condition holds. Should there be other way to express this operation from the perspective of something like...dynamically assigning values onto an array?

4

2 回答 2

1

First, your code is slightly inefficient in the double do-loop. Suppose you have only 5 firms, then your loop will count them as

(1,1), (1,2), (1,3), (1,4), (1,5)

(2,1), (2,2), (2,3), (2,4), (2,5)

(3,1), (3,2), (3,3), (3,4), (3,5)

(4,1), (4,2), (4,3), (4,4), (4,5)

(5,1), (5,2), (5,3), (5,4), (5,5)

You probably don't want to compute the distance from location 1 to location 1 since it'll be 0 as it is the same firm. You probably also don't want to count (2,1) since you've already done the work for (1,2). What you can do instead is

do i=1,nr
   do j=i+1,nr
      ...
   enddo
enddo

However, if you do want to count (1,2) and (2,1), you'd have to do

do i=1,nr
   do j=1,nr
      if(j == i) cycle
      ...
   enddo
enddo

which will skip j=i and go to j=i+1.


As to your actual question, I would think a 1D array, i.e. allocate(n_neighbor(nr)), is what you need. If we consider adjacent to be within that same 0.3 km, then you could do

if(distkm(lat(i), lon(i), lat(j), lon(j)) <= 0.3) then
   jobs_within(j) = jobs(j)
   n_neighbors(j) = n_neighbors(j) + 1
else
   jobs_within(j) = 0
endif

where we have initialized n_neighbors=0.

Though I don't quite understand the context of your problem, it seems to me that the index of jobs_within ought to be i and not j and that you probably want to sum them, i.e. jobs_within(i) = jobs_within(i) + jobs(j). If this is not the case, feel free to ignore the comment.

于 2013-11-14T13:41:44.303 回答
0

I'm not entirely sure what you really want, but just guessing it sounds as if you can write something like:

n_neighbor(j)=jobs(j) 

in your else part. If you want a better answer, please take out all the unnecessary stuff of your code.And then sum it the same way as you did for jobs_within.

于 2013-11-14T10:06:25.610 回答