如何在Fortran中排列向量的元素?

发布于 2024-08-16 19:20:42 字数 467 浏览 5 评论 0原文

我有两个 p*n 数组,y 和 ymiss。 y 包含实数和 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),所以其余的是什么并不重要。

问题是,我怎样才能在 Fortran 中做类似的事情呢?

谢谢,

朱尼

I have two p*n arrays, y and ymiss. y contains real numbers and NA's. ymiss contains 1's and 0's, so that if y(i,j)==NA, ymiss(i,j)==0, and 1 otherwise. I also have 1*n array ydim which tells how many real numbers there is at y(1:p,n), so ydim has values 0 to p

In R programming language, I can do following:

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

That code arranges all real numbers of y(,t) in like this

first there's for example
y(,t) = (3,1,NA,6,2,NA)
after the code it's
y(,t) = (3,1,6,2,2,NA)

Now I will only need those first 1:ydim(t), so it doesn't matter what those rest are.

The question is, how can I do something like that in Fortran?

Thanks,

Jouni

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

戏剧牡丹亭 2024-08-23 19:20:42

“where 语句”和“merge”内部函数功能强大,可在数组中的选定位置上进行操作,但它们不会将项目移动到数组的前面。使用具有显式索引的老式代码(可以打包到函数中),例如:

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

您想要的可以使用“pack”内在函数通过数组内在函数来完成。将 ymiss 转换为逻辑数组:0 --> .false., 1 --> .true.. 然后使用如下代码(在没有第二个索引的情况下进行测试):

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


编辑以添加示例代码,显示 Fortran 内在函数“where”、“count”和“pack”的使用。仅“where”无法解决问题,但“pack”可以。在本例中,我使用“< -90”作为 NaN。 OP 不需要步骤“y (ydim+1:LEN) = -99.0”,因为他们不需要使用这些元素。

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

使用 where 进行掩码,不重新排列:
3.0 1.0 -99.0 6.0 2.0 -99.0

使用 pack 后,并“擦除”末尾:
3.0 1.0 6.0 2.0 -99.0 -99.0

The "where statement" and the "merge" intrinsic function are powerful, operating on selected positions in arrays, but they don't move items to the front of an array. With old-fashioned code with explicit indexing (could be packaged into a function) e.g.:

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

What you want could be done with array intrinsics using the "pack" intrinsic. Convert ymiss into a logical array: 0 --> .false., 1 --> .true.. Then use code like (tested without the second index):

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


Edit to add example code, showing use of Fortran intrinsics "where", "count" and "pack". "where" alone can't solve the problem, but "pack" can. I used "< -90" as NaN for this example. The step "y (ydim+1:LEN) = -99.0" isn't required by the OP, who doesn't need to use these elements.

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

Output is:

The input array:
3.0 1.0 -99.0 6.0 2.0 -99.0

Masking with where does not rearrange:
3.0 1.0 -99.0 6.0 2.0 -99.0

After using pack, and "erasing" the end:
3.0 1.0 6.0 2.0 -99.0 -99.0

余生一个溪 2024-08-23 19:20:42

在 Fortran 中,你不能将 na 存储在实数数组中,只能存储实数。因此,您可能希望将 na 替换为数据中不太可能出现的某个值:huge() 可能合适。 2D 数组对于 Fortan 来说完全没有问题。您可能想要使用逻辑的 2D 数组来替换 ymiss,而不是 1 和 0 的 2D 数组。

没有简单的、内在的来实现你想要的,你需要编写一个函数。然而,更适合 Fortran 的处理方式是使用逻辑数组作为要执行的操作的掩码

因此,这里有一些未经测试的 Fortran 代码片段:

! 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

In Fortran you can't store na in an array of real numbers, you can only store real numbers. So you'll probably want to replace na's with some value not likely to be present in your data: huge() might be suitable. 2D arrays are no problem at all for Fortan. You might want to use a 2D array of logicals to replace ymiss rather than a 2D array of 1s and 0s.

There is no simple, intrinsic to achieve what you want, you'd need to write a function. However, a more Fortran way of doing things would be to use the array of logicals as a mask for the operations you want to carry out.

So, here's some fragmentary Fortran code, not tested:

! 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文