Как расположить элементы вектора в Фортране?

У меня есть два массива 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), поэтому не имеет значения, что это за остальные.

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

Спасибо,

Jouni

2 ответа

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

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))


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

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

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

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

Итак, вот некоторый фрагментарный код на Фортране, не проверенный:

! 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
Другие вопросы по тегам