我正在将 FORTRAN 代码转换为 R,但遇到了条件求和的问题。
我的代码的一些上下文: 我正在观察每小时表面上的质量积累以及雨水清洁表面的情况。如果降雨量低于 1.5 厘米的阈值,则对数小时内的质量累积进行求和,但如果降雨量高于 1.5 厘米的阈值,则清除质量累积总和并将其重置为零。在接下来的几个小时内,重复该过程,对质量累积进行求和,直到降雨量高于 1.5,然后将质量累积设置回零。
因此,在 FORTRAN 中,我将逐行遍历数组(使用 DO LOOP)并计算该小时的总质量积累“mtot”。如果该小时内对应的降雨量小于 1.5 厘米,我会将这个 mtot 值汇总为“msum”。如果降雨量高于 1.5,则 msum 和 mtot 将设置为零,因为现在表面在该小时内没有经历质量积累,并且之前的质量已被清除。然后我进入下一次迭代并重新计算该小时的 mtot 并重复相同的逻辑。因此,我将 i+1 小时的 mtot 存储在 i 小时的 mtot 上。
这是我的 FORTRAN 代码:
DO i = 1, 8760
...
mtot = ...
IF (rain_hourly(i) >= 1.5) THEN ! did it rain, was the rain enough to clean the surface, threshold to clean is 1.5 cm an hour
msum = 0.0
mtot = 0.0
ELSE ! sum mass on surface if it didnt rain enough
msum = msum + mtot
END IF
...
END DO
我需要帮助的地方是将我的 IF block 转换为 R。在 R 中,我立即计算每个小时的 mtot,并为每个小时提供一组 mtot。我想我正在寻找一个条件 if 将值相加,直到每小时 mtot 数组中看到的最后一个零。我是 R 新手,不确定如何处理它。我可以想出许多不同的方法来在 FORTRAN 中做到这一点,但就像我说的,我是 R 的新手,不太了解 R 的基本思维方式。
我创建了一个表格来帮助更好地解释我正在尝试做的事情。每小时雨柱包含一小时内经历的降雨量(以厘米为单位),回想一下,清洁表面的阈值是 1.5 厘米。每小时 mtot 列是每小时累积的质量量。请注意,如果每小时雨柱达到阈值 1.5,则该小时的每小时 mtot 将被零覆盖。最后,如果未达到降雨阈值,则求和 mtot 列是同一行 mtot 与过去 mtot 的总和。请注意,总和中包含的过去 mtot 只会返回到上次达到降雨阈值时。
**每小时降雨量** **每小时 mtot** **mtot 总和**
1 3 3
1 1 4
1 2 6
1.5 0 -> 1 0
1 2 2
1.5 0 -> 1 0
1 3 3
1 1 4
1 1 5
最佳答案
与 data.table
包可以作为“one-liner”实现:
library(data.table)
data.table(DF)[, new := (hourly.rain < 1.5) * cumsum(hourly.mtot),
by = rleid(hourly.rain < 1.5)][]
hourly.rain hourly.mtot summed.mtot new 1: 1.0 3 3 3 2: 1.0 1 4 4 3: 1.0 2 6 6 4: 1.5 1 0 0 5: 1.0 2 2 2 6: 1.5 1 0 0 7: 1.0 3 3 3 8: 1.0 1 4 4 9: 1.0 1 5 5
rleid(hourly.rain < 1.5)
为低于或等于/高于阈值的每个值条纹创建一个唯一的组 ID。在各组内重新开始累积和的计算。与 rleid(hourly.rain < 1.5)
的乘法当达到或超过阈值时,强制结果变为零。在此,使用了 TRUE 和 FALSE 在强制转换为数字类型时分别变为 1 和 0 的事实。
数据
DF <- structure(list(hourly.rain = c(1, 1, 1, 1.5, 1, 1.5, 1, 1, 1),
hourly.mtot = c(3L, 1L, 2L, 1L, 2L, 1L, 3L, 1L, 1L), summed.mtot = c(3L,
4L, 6L, 0L, 2L, 0L, 3L, 4L, 5L)), .Names = c("hourly.rain",
"hourly.mtot", "summed.mtot"), row.names = c(NA, -9L), class = "data.frame")
关于r - 将条件和从 FORTRAN 转换为 R,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44865799/