Как расположить элементы вектора в Фортране? - PullRequest
2 голосов
/ 05 января 2010

У меня есть два массива p * n, y и ymiss. у содержит действительные числа и NA. ymiss содержит 1 и 0, так что если y (i, j) == NA, ymiss (i, j) == 0 и 1 в противном случае. У меня также есть 1 * n массив ydim, который сообщает, сколько вещественных чисел в y (1: p, n), поэтому ydim имеет значения от 0 до p

На языке программирования R я могу сделать следующее:

if(ydim!=p && ydim!=0)  
  y(1:ydim(t), t) = y(ymiss(,t), t)

Этот код упорядочивает все действительные числа y (, t) следующим образом

сначала есть например y (, t) = (3,1, NA, 6,2, NA) после кода это y (, t) = (3,1,6,2,2, NA)

Теперь мне понадобятся только первые 1: ydim (t), поэтому не имеет значения, что это за остальные.

Вопрос в том, как я могу сделать что-то подобное в Фортране?

Спасибо

Джуни

Ответы [ 2 ]

2 голосов
/ 05 января 2010

Оператор where и встроенная функция merge мощны, работают с выбранными позициями в массивах, но не перемещают элементы в начало массива. Со старомодным кодом с явной индексацией (может быть упакован в функцию), например ::100100

k=1
do i=1, n
   if (ymiss (i) == 1) then
      y(k) = y(i)
      k = k + 1
   end if
end do

То, что вы хотите, может быть сделано с помощью встроенных массивов с помощью встроенного пакета. Преобразуйте ymiss в логический массив: 0 -> .false., 1 -> .true .. Затем используйте код наподобие (проверено без второго индекса):

y (1: ydim (t), t) = pack (y (:, t), ymiss (:, t))


Изменить, чтобы добавить пример кода, показывающий использование встроенных в Фортран "где", "count" и "pack". «где» один не может решить проблему, но «упаковать» можно. Я использовал "<-90" в качестве NaN для этого примера. ОП "y (ydim + 1: LEN) = -99.0" не требуется для ОП, которому не нужно использовать эти элементы. </p>

program test1

integer, parameter :: LEN = 6
real, dimension (1:LEN) :: y = [3.0, 1.0, -99.0, 6.0, 2.0, -99.0 ]
real, dimension (1:LEN) :: y2
logical, dimension (1:LEN) :: ymiss
integer :: ydim

y2 = y
write (*, '(/ "The input array:" / 6(F6.1) )' )  y

where (y < -90.0)
   ymiss = .false.
elsewhere
   ymiss = .true.
end where

ydim = count (ymiss)

where (ymiss) y2 = y
write (*, '(/ "Masking with where does not rearrange:" / 6(F6.1) )' )  y2

y (1:ydim) = pack (y, ymiss)
y (ydim+1:LEN) = -99.0
write (*, '(/ "After using pack, and ""erasing"" the end:" / 6(F6.1) )' )  y


stop

end program test1

Вывод:

входной массив: 3,0 1,0 -99,0 6,0 2,0 -99,0

Маскировка с куда не переставляет: 3,0 1,0 -99,0 6,0 2,0 -99,0

После использования пакета и «стирания» конца: 3,0 1,0 6,0 2,0 -99,0 -99,0

1 голос
/ 05 января 2010

В Фортране вы не можете хранить данные в массиве действительных чисел, вы можете хранить только действительные числа. Так что вы, вероятно, захотите заменить na на какое-то значение, которое вряд ли будет присутствовать в ваших данных: огромный () может подойти. 2D-массивы вообще не проблема для Фортана. Возможно, вы захотите использовать двумерный массив логики для замены ymiss, а не двумерный массив из 1 и 0.

Нет простого, встроенного в достижение того, чего вы хотите, вам нужно написать функцию. Тем не менее, более правильным способом Фортрана было бы использование массива логики как маска для операций, которые вы хотите выполнить.

Итак, вот фрагментарный код на Фортране, который не тестировался:

! Declarations
real(8), dimension(m,n) :: y, ynew
logical, dimension(m,n) :: ymiss

! Executable
where (ymiss) ynew = func(y)  ! here func() is whatever your function is
...