Problem
I am having issues passing variables I am creating in a summarize() statement, using functions defined below, and passing those same variables into new functions within the same summarize statement.
Goal
Thus far, using the functions defined below as find_mountain() and find_valley() I create the mountain and valley variables in a summarize statement. Those variables are then one of two respective variables passed to the functions find_first_zero() and find_first_non_zero(). The mountain and valley variables are used in their respective functions to restrict parsing through a vector of data, termed elevation. The goal is for these to return either the first location of a zero value in the vector after the location of the mountain and the first location of a non-zero value after the location of the valley.
Error
Everything works up to this passing and then I get this:
Error: Problem with `summarise()` input `i_mountain_shore`.
x missing value where TRUE/FALSE needed
ℹ Input `i_mountain_shore` is `find_first_zero(elevation, mountain)`.
ℹ The error occurred in group 1: timestep = "55".
Run `rlang::last_error()` to see where the error occurred.
Reprex
All data necessary is included via the link in the code, thanks @technocrat
-issues start at 'i_mountain_shore'
library(forcats)
library(tidyverse)
library(dplyr)
library(zoo)
library(peakPick)
library(tidyr)
# Data
transect <- readr::read_csv("https://raw.githubusercontent.com/Bryanrt-geophys/Thesis/Thesis/r_code/transect.csv")
transect = transect[-1]
# Pivot to long format
long_transect <- transect %>%
pivot_longer(-Y,
names_to = "timestep",
names_prefix="Z_",
values_to = "elevation") %>%
mutate(elevation = if_else(abs(elevation) < 10, 0, elevation)) # say that <0 is = 0
long_transect$timestep = fct_inorder(long_transect$timestep)
# used to find the mountains
find_mountain <- function(elevation_smooth, elevation){
peaks_high <- which(peakPick::peakpick(elevation_smooth,
neighlim = 20,
deriv.lim = 100,
peak.min.sd = 5))
peaks_high <- peaks_high[peaks_high > 200 & peaks_high < 800]
if(length(peaks_high) == 0){
warning("Too many peaks")
mountain <- NA
} else if(length(peaks_high) == 1){
mountain <- peaks_high
} else if(length(peaks_high) == 2 && elevation[peaks_high[2]] < 0){
# second mountain
mountain <- peaks_high[1]
} else if(length(peaks_high) == 2 && elevation[peaks_high[2]] > 0){
# second mountain
mountain <- peaks_high[2]
} else{
warning("Too many peaks")
mountain <- NA
}
return(c("mountain" = mountain))
}
# used to find the valleys
find_valley <- function(elevation_smooth, elevation){
peaks_high <- which(peakPick::peakpick(elevation_smooth,
neighlim = 20,
deriv.lim = 100,
peak.min.sd = 5))
peaks_high <- peaks_high[peaks_high > 200 & peaks_high < 800]
if(length(peaks_high) == 0){
warning("Too many peaks")
valley <- NA
} else if(length(peaks_high) == 1){
valley <- peaks_high
valley <- peaks_high + which.min(elevation[peaks_high:length(elevation)])
} else if(length(peaks_high) == 2 && elevation[peaks_high[2]] < 0){
# second valley
valley <- peaks_high[1]
#second valley
valley <- peaks_high[1]+which.min(elevation[peaks_high[1]:length(elevation)])
} else if(length(peaks_high) == 2 && elevation[peaks_high[2]] > 0){
# second valley
valley <- peaks_high[2]
#second valley
valley <- peaks_high[2]+which.min(elevation[peaks_high[2]:length(elevation)])
} else{
warning("Too many peaks")
valley <- NA
}
return(c("valley" = valley))
}
# used to find valley-side of basin
find_first_non_zero <- function(elevation_vector, valley){
start_at <- elevation_vector[valley] # the position of the minimum
if(elevation_vector[start_at] > 0){
warning("The lowest point is positive! Returning NA.")
return(NA)
}
subset_positions <- seq(start_at, length(elevation_vector))
pos <- first(which(elevation_vector[subset_positions] >= 0))
pos + start_at
}
# used to find mountain-side of basin
find_first_zero <- function(elevation_vector, mountain){
start_at <- elevation_vector[mountain] # the position of the minimum
if(elevation_vector[start_at] > 0){
warning("The lowest point is positive! Returning NA.")
return(NA)
}
subset_positions <- seq(start_at, length(elevation_vector))
pos <- first(which(elevation_vector[subset_positions] <= 0))
pos + start_at
}
long_transect <- long_transect %>%
group_by(timestep) %>%
mutate(elevation_smooth = smooth.spline(elevation, spar=.5)$y)
basin_geometry <- long_transect %>%
group_by(timestep) %>%
summarize(mountain = find_mountain(elevation_smooth, elevation),
valley = find_valley(elevation_smooth, elevation),
i_lowest_point = which.min(elevation),
i_mountain_shore = find_first_zero(elevation, mountain),
i_valley_shore = find_first_non_zero(elevation, valley),
Z_lowest_point = elevation[i_lowest_point],
Z_mountian_shore = elevation[i_mountain_shore],
Z_valley_level = elevation[i_valley_shore],
Y_lowest_point = Y[i_lowest_point],
Y_mountain_shore = Y[i_mountain_shore],
Y_valley_shore = Y[i_valley_shore]) %>%
mutate(basin_width = Y_mountain_shore - Y_valley_shore) %>%
mutate(My = c(1:(ncol(transect)-1)))