2012-08-27 99 views
1

我有一個數據大概一百萬條記錄,每條記錄有6個浮點數。我想查找具有相同六個值的記錄集合,理想情況下我想在Fortran中執行此操作,因爲剩下的處理過程是在Fortran中完成的。對此的推薦方法是什麼?最後,我想從原始索引映射到新索引,這是這些數據集的精簡版本,而不會有重複。每條記錄都有其他屬性,我有興趣根據這六個屬性來聚合這些屬性。在fortran中查找重複記錄

我試圖通過將輸出導出爲csv來將它們導入到MS Access中,然後發現這些集合的查詢需要10秒左右才能運行。我寫了一個代碼,這個(「線性搜索」?),但有百萬條記錄在10分鐘左右沒有完成,我剛剛放棄了這種方法。

我現在正在考慮的方法是調整slatecorderpack的排序/排序程序,我認爲這比我的原始代碼更好。但我想知道這樣的事情是否已經完成,我可以下載,或者如果有更好的方法。

編輯:

我說:「發現重複的」,但我確實需要從原始數據記錄到這個縮減集的映射。我想要像imap(1:n)這樣的映射數組,其中imap(1),imap(4),imap(5)具有相同的值,如果這些浮點數是pt。原始記錄1,4和5中的值是相同的。希望這不是太多從我原來說的偏差...

+0

你是在尋找確切的二進制相等,還是像abs(x-y) agentp

+1

可能的算法:http://stackoverflow.com/questions/1532819/algorithm-efficient-way-to-remove-duplicate-integers-from-an-array –

+0

@george,準確的二進制相等是適用於我的應用程序,我相信使編程更容易。我知道我的代碼適用於較小的尺寸。可移植性很好,但我不介意在Linux環境中使用一些廣泛使用的實現,如果這使得事情變得更容易(我正在使用PGI編譯器在Linux上進行編程)。 – yosukesabai

回答

1

這就是我最終做的...我從ORDERPACK代碼mrgrnk,並適合我的目的。下面的子程序findmap似乎正在做我想做的事情。

module fndmap 
use m_mrgrnk, only:mrgrnk 
implicit none 
contains 
    subroutine findmap(stkprm, stkmap) 
    ! given 2-d real array stkprm, find a mapping described below: 
    ! 
    ! (identical records are assigned with same index) 
    ! stkmap(i) == stkmap(j) iff stkprm(:,i) == stkprm(:,j) 
    ! (order conserved) 
    ! if i < j and stkmap(i) /= stkmap(j), then stkmap(i) < stkmap(j) 
    ! (new index are contiguous) 
    ! set(stkmap) == {1,2,..,maxval(stkmap)} 
    ! 
    real,dimension(:,:),intent(in) :: stkprm 
    integer,dimension(:), intent(out) :: stkmap 
    integer, dimension(size(stkprm,2)) :: irngt 
    integer, dimension(size(stkprm,2)) :: iwork 
    integer :: nrec, i, j 
    nrec = size(stkprm,2) 
    ! find rank of each record, duplicate records kept 
    call ar_mrgrnk(stkprm, irngt) 

    ! construct iwork array, which has index of original array where the 
    ! record are identical, and the index is youguest 
    i = 1 
    do while(i<=nrec) 
     do j=i+1,nrec 
     if (any(stkprm(:,irngt(i))/=stkprm(:,irngt(j)))) exit 
     enddo 
     iwork(irngt(i:j-1)) = minval(irngt(i:j-1)) 
     i = j 
    enddo 

    ! now construct the map, where stkmap(i) shows index of new array 
    ! with duplicated record eliminated, original order kept 
    j = 0 
    do i=1,nrec 
     if (i==iwork(i)) then 
     j = j+1 
     stkmap(i) = j 
     else 
     stkmap(i) = stkmap(iwork(i)) 
     endif 
    enddo 
    end subroutine 

    recursive subroutine ar_mrgrnk(xdont, irngt) 
    ! behaves like mrgrnk of ORDERPACK, except that array is 2-d 
    ! each row are ranked by first field, then second and so on 
    real, dimension(:,:), intent(in) :: xdont 
    integer, dimension(:), intent(out), target :: irngt 
    integer, dimension(size(xdont,2)) :: iwork 

    integer :: nfld,nrec 
    integer :: i, j 
    integer, dimension(:), pointer :: ipt 

    nfld=size(xdont,1) 
    nrec=size(xdont,2) 

    ! rank by the first field 
    call mrgrnk(xdont(1,:), irngt) 

    ! if there's only one field, it's done 
    if (nfld==1) return 

    ! examine the rank to see if multiple record has identical 
    ! values for the first field 
    i = 1 
    do while(i<=nrec) 
     do j=i+1,nrec 
     if (xdont(1,irngt(i))/=xdont(1,irngt(j))) exit 
     enddo 
     ! if one-to-one, do nothing 
     if (j-1>i) then 
     ! if many-to-one, 
     ! gather those many, and rank them 
     call ar_mrgrnk(xdont(2:,irngt(i:j-1)),iwork) 
     ! rearrange my rank based on those fields to the right 
     ipt => irngt(i:j-1) 
     ipt = ipt(iwork(1:j-i)) 
     endif 
     i = j 
    enddo 
    if(associated(ipt)) nullify(ipt) 
    end subroutine 
end module