Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problema al interpolar profundidades (spline) #34

Closed
raulpoppiel opened this issue Jul 29, 2022 · 14 comments
Closed

Problema al interpolar profundidades (spline) #34

raulpoppiel opened this issue Jul 29, 2022 · 14 comments

Comments

@raulpoppiel
Copy link

raulpoppiel commented Jul 29, 2022

Estimad@s,

Mi problema es sobre un mensaje de error (ver abajo) cuando intento interpolar valores de atributos del suelo en intervalos de profundidades con el método splines del paquete SISINTAR.

Error in metodo_fun(profundidad_superior, profundidad_inferior, get(var),  : 
  !!

Logre bajar los datos del servidor de SISINTA al PC e importarlos en R. Después de eso, apliqué las siguientes líneas de código al conjunto completo Perfiles_sisinta.csv

Working_Directory <- "C:/Users/YOUR-DIRECTORY"
setwd(Working_Directory);getwd()

library(SISINTAR)
library(dplyr)

# Importing soil profiles data from PC
profiles <- read.csv("Perfiles_sisinta.csv", header = TRUE, sep = ",", dec = ".", na.strings = "NA",check.names=FALSE,fileEncoding = "UTF-16LE")

# Imputing missing depths and quantifying NAs by depth
profiles <- profiles %>% imputar_profundidad_inferior() %>%
  group_by(perfil_id) %>%
  mutate(prof.por.perfil=n()) %>%
  mutate(NAs.por.prof.sup=sum(is.na(profundidad_superior))) %>%
  mutate(NAs.por.prof.inf=sum(is.na(profundidad_inferior))) %>%
  ungroup()

# Getting layers with NAs for Upper and Lower depths
perfis.NAs.prof.sup <- profiles %>% filter(NAs.por.prof.sup >= 1) %>% select(perfil_id,profundidad_superior,profundidad_inferior,prof.por.perfil,NAs.por.prof.sup,NAs.por.prof.inf)
perfis.NAs.prof.inf <- profiles %>% filter(NAs.por.prof.inf >= 1) %>% select(perfil_id,profundidad_superior,profundidad_inferior,prof.por.perfil,NAs.por.prof.sup,NAs.por.prof.inf)

# Splitting data into sets with
# -> one (1) layer (depth): not interpolable
# -> several (>1) layers (depths): interpolable
profiles.one.layer <- profiles %>%
  mutate(profile.remove1 = if_else(prof.por.perfil <= 1, TRUE, FALSE)) %>%
  mutate(profile.remove2 = if_else(NAs.por.prof.sup <= 0 & NAs.por.prof.inf <= 0, TRUE, FALSE)) %>%
  filter(profile.remove1=="TRUE" & profile.remove2=="TRUE") %>% select(-c(profile.remove1,profile.remove2))

profiles.several.layers <- profiles %>%
  mutate(profile.remove1 = ifelse(prof.por.perfil > 1, TRUE, FALSE)) %>%
  mutate(profile.remove2 = ifelse(NAs.por.prof.sup <= 0 & NAs.por.prof.inf <= 0, TRUE, FALSE)) %>%
  filter(profile.remove1=="TRUE" & profile.remove2=="TRUE") %>% select(-c(profile.remove1,profile.remove2))


# Depth interpolation using the set with several layers (depths)
# Using all data of the set 
# (THIS RETURNED AN ERROR MESSAGE, EVEN WHEN FILTERING NAs FROM DEPTHS AND ARCILLA)
profiles.spline <- profiles.several.layers %>% 
#  filter(!is.na(profundidad_superior)) %>% filter(!is.na(profundidad_inferior)) %>%
#  filter(!is.na(arcilla)) %>% filter(!is.na(arcilla)) %>%
  imputar_profundidad_inferior() %>%
  interpolar_perfiles(variables = c("arcilla"),
                      horizontes = seq(0, 100, 20),
                      metodo = interpolar_spline(lambda = 0.1),
                      parar_en_error = FALSE)
  
# Using a subset (THIS WROKED FINE)
profiles.spline.teste1 <- profiles.several.layers %>% slice(1:200) %>%
  imputar_profundidad_inferior() %>%
  interpolar_perfiles(variables = c("arcilla"),
                      horizontes = seq(0, 100, 20),
                      metodo = interpolar_spline(lambda = 0.1),
                      parar_en_error = FALSE)

# Using a 2nd subset (THIS RETURNED AN ERROR MESSAGE)
profiles.spline.teste2 <- profiles.several.layers %>% slice(200:300) %>%
  imputar_profundidad_inferior() %>%
  interpolar_perfiles(variables = c("arcilla"),
                      horizontes = seq(0, 100, 20),
                      metodo = interpolar_spline(lambda = 0.1),
                      parar_en_error = FALSE)

Para intentar identificar el error, he realizado varias pruebas dividiendo los datos en conjuntos menores (ver arriba), donde la interpolación funcionó bien para algunos conjuntos y para otros retornó el mismo mensaje de error. Después, comparé los datos de los conjuntos y me parecieron iguales, entonces, no conseguí identificar cual sería la fuente del problema.

Mi sospecha es que el valor de la profundidad inferior (para la camada anterior) no sea el mismo de la profundidad superior (para la camada siguiente), provocando una discontinuidad que impide el funcionamiento del código y retornando el mensaje de error. Uds. tienen algun codigo que realice esa verificación?

Yo necesito interpolar los datos desde 0 a 100 cm en intervalos de 20 cm usando splines.

Desde ya, agradezco cualquier tipo de ayuda.

Saludos
Raul.

@eliocamp
Copy link
Contributor

eliocamp commented Jul 29, 2022

Hola, el problema es que algunos perfiles tienen capas solapadas. Por ejemplo, el perfil 272 tiene una capa que va del 22 al 38 y la siguiente va del 35 al 58.

library(dplyr)
SISINTAR::get_perfiles(272) |> 
  select(profundidad_superior, profundidad_inferior)
#>   profundidad_superior profundidad_inferior
#> 1                    0                   22
#> 2                   22                   38
#> 3                   35                   58
#> 4                   58                   80

Created on 2022-07-29 by the reprex package (v2.0.1)

El método falla porque hay puntos que están entre dos capas vez de una.

Que yo sepa, no hay problema con que haya saltos entre capas. La interpolación te dará NAs, creo.

Podés filtrar esos perfiles con este código:

# Filtra perfiles con capas donde la profundidad superior es menor que la profundidad 
# inferior de la capa anterior. 
malos <- profiles |> 
  group_by(perfil_id) |> 
  filter(profundidad_superior < lag(profundidad_inferior)) |>   
  pull(perfil_id) |> 
  unique()

profiles <- filter(profiles, !perfil_id %in% malos)

(Son unos cuantos:

> malos
 [1]  272  350  576  687  765  913 1287 2545 2855 3147 3177 3206
[13] 3295 3621 3745 3753 3795 3809 3839 3846 3856 3900 3907 3908
[25] 3909 3924 4055 4129 4139 4165 4222 4230 4235 4247 4276 4311
[37] 4320 4419 4896 4904 4918 5155 5188 5191 5230 5344 5490 5550
[49] 5871 6052 6151 6186 6263 6468 6773 6795 6838 6897 7331

)
Si no querés filtrarlos, podrías reemplazar las profundidades para que sean consistentes, ya sea modificando la profundiad inferior de una capa o la superior de la siguiente.

@angelini75 @dariorodriguez ¿Qué habría que hacer en estos casos? ¿Son un error de la base o es una observación posible que hay que tener en cuenta en la interpolación?

@dariorodriguez
Copy link

dariorodriguez commented Jul 29, 2022 via email

@paocorrales
Copy link
Contributor

Hola Dario, los perfiles que tienen ese problema (al menos en el archivo de Raúl) están ahora listados en la respuesta de Elio.

@raulpoppiel
Copy link
Author

Muchas gracias a todos, fueron muy amables y rápidos.

Adicionando el filtro elaborado por Elio, ahora mi codigó funcionó.
Excelente paquete de herramientas para auxiliar a la Pedometria!

Saludos.
Raul.

@dariorodriguez
Copy link

dariorodriguez commented Jul 30, 2022 via email

@raulpoppiel
Copy link
Author

Una opción seria mantener la descripción morfológica original, y al lado adicionar las profundidades para fines de análisis de datos.

Descripción morfológica original

Sup Inf Hor
7 0 Horizonte Orgánico
0 15 Horizonte A
15 30 Horizonte B

Para fines de análise de datos (la profundidad superior del horizonte más superficial tendria valor cero, adicionando un valor constante a las demás profundidades)

Sup Inf Sup Inf Hor
0 (0+7) 0 7 Horizonte Orgánico
(0+7) (15+7) 7 22 Horizonte A
(15+7) (30+7) 22 37 Horizonte B

Abrazos.
Raul

@eliocamp
Copy link
Contributor

Si el perfil arranca "más arriba" se cero, entonces lo más natural sería usar profundidad negativa, quizás?

@raulpoppiel
Copy link
Author

Además, la consistencia de los datos deveria ser analizada.
Por ejemplo, verificando si los valores de: i) Arena Total + Limo Total + Arcilla = 100%, ii) carbono orgánico disminuyen con la profundidad, iii) suma de bases y CIC fueron bien calculados, etc.

@dariorodriguez
Copy link

dariorodriguez commented Aug 1, 2022 via email

@dariorodriguez
Copy link

dariorodriguez commented Aug 1, 2022 via email

@raulpoppiel
Copy link
Author

raulpoppiel commented Aug 1, 2022

@dariorodriguez Ok, entendi.

Entonces, Ud. recomienda filtrar (remover) los horizontes organicos (para suelos minerales) del conjunto de datos antes de iniciar um mapeo digital de carbono orgánico del suelo?

En qué casos los horizontes organicos deverian considerarse (talvez para suelos organicos)?

Estas discussiones son muy importantes.
Desde ya, muchas gracias.

@dariorodriguez
Copy link

dariorodriguez commented Aug 1, 2022 via email

@eliocamp
Copy link
Contributor

eliocamp commented Aug 1, 2022

Hola, como el problema original ya se resolvió, voy a cerrar este issue y seguimos sobre el tema del horizonte orgánico en teste otro issue: #35

Reproduje los comentarios sobre el tema en ese issue para que quede toda la conversación en un lugar. No pasé las consultas metodológicas que no están relacionadas sobre cómo representar esos datos en la base de datos.

@eliocamp eliocamp closed this as completed Aug 1, 2022
@dariorodriguez
Copy link

dariorodriguez commented Oct 11, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants