使用 'apply' 函数在 R 中执行带有条件语句的代码

Use an 'apply' function to perform code with conditional statements in R

我一直在做一个项目,我需要在数据集中找到峰和谷(不仅仅是每列的最高数字,而是所有的峰和谷)。 我确实设法让它在 1 列上工作,但我为此使用了一个 for 循环,我需要对大约 50 列执行此操作,所以我认为我应该使用 'apply' 函数。我只是不知道该怎么做。我可以将 'if' 语句等放在 'apply' 函数中吗?

这是我用来检查一列的内容: ('First' 是数据集的名称,'Seq1' 是第一列)

Lowest = 0
Highest = 0
Summits = vector('numeric')
Valleys = vector('numeric')

for (i in 1:length(First$Seq1))
{
    if (!is.na(First$Seq1[i+1]))
    {
        if (First$Seq1[i] < Lowest) {Lowest = First$Seq1[i]}
        if (First$Seq1[i] > Highest) {Highest = First$Seq1[i]}  

        if (First$Seq1[i] > 0 && First$Seq1[i+1] < 0) 
        { Summits <- append(Summits, Highest, after=length(Summits)) }
        if (First$Seq1[i] < 0 && First$Seq1[i+1] > 0) 
        { Valleys <- append(Valleys, Lowest, after=length(Summits)) }
    }
}

当然可以!我会首先定义一个辅助函数来定义要对一个特定列执行的操作,然后在 apply:

中调用该函数
    HelperFun <- function(x) {
    # your code from above, replacing 'Seq1' by x
    }
    apply(First, 2, HelperFun)

*apply 函数并不比 for 循环更好,前提是您不在 for 循环中生成对象。您绝不能在循环中使用 append。预分配您的结果对象并填充它。

这将找到网格上的所有局部最小值:

#an example
set.seed(42)
plane <- matrix(rnorm(100, sd = 5), 10)

#plot
library(raster)
plot(raster(plane))

#initialize a logical matrix
res <- matrix(TRUE, ncol = ncol(plane), nrow = nrow(plane))

#check for each subgrid of 2 times 2 cells which of the cells is the minimum
for (i in 1:(nrow(plane) - 1)) {
  for (j in 1:(ncol(plane) - 1)) {
    inds <- as.matrix(expand.grid(r = i + 0:1, c = j + 0:1))
    #cell must be a minimum of all 4 subgrids it is part of
    res[inds] <- res[inds] & plane[inds] == min(plane[inds])
  }
}

print(res)
plane[res]
#[1] -13.282277  -8.906542  -8.585043 -12.071038  -3.919195 -14.965450  -5.215595  -5.498904  -5.971644  -2.380870  -7.296070

#highlight local minima
plot(rasterToPolygons(raster(res)), border = t(res), add = TRUE)

library(reshape2)
res1 <- melt(res)
res1 <- res1[res1$value,]
text(x = res1$Var2 /10 - 0.05, 
     y = 1-res1$Var1 /10 + 0.05, 
     labels = round(plane[res],1))

我在这里假设对角邻居被算作邻居,而不仅仅是同一列或行中的邻居。但这将是微不足道的改变。

我知道这不是您想要的解决方案 --- 您有一维时间序列,但这是 Roland 解决方案的(更直接的)变体。

#example data
set.seed(42)
plane <- matrix(rnorm(100, sd = 5), 10)
library(raster)
r <- raster(plane)

f <- focal(r, matrix(1,3,3), min, pad=TRUE, na.rm=TRUE) 
x <- r == f
mins <- mask(r, x, maskvalue=FALSE)

pts <- rasterToPoints(mins)
cells <- cellFromXY(x, pts)

r[cells]

plot(r)
text(mins, digits=1)
plot(rasterToPolygons(mins), add=TRUE)