使用 '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)
我一直在做一个项目,我需要在数据集中找到峰和谷(不仅仅是每列的最高数字,而是所有的峰和谷)。 我确实设法让它在 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)