A compreensão dos sinais vitais inicia-se pela definição dos conceitos de saúde e doença. Segundo a Organização Mundial da Saúde (OMS), saúde é “um estado de completo bem-estar físico, mental e social, e não apenas a ausência de doença ou enfermidade” (OMS, 1946). Embora essa definição tenha representado um avanço conceitual importante, diversos autores destacam suas limitações práticas. Segre e Ferraz (1997), por exemplo, argumentam que a ideia de “completo bem-estar” é idealizada e dificilmente alcançável, tornando a definição pouco operacional para a prática clínica.
Independentemente das discussões conceituais, a medicina moderna baseia-se na premissa de que a saúde está associada à capacidade do organismo de manter a estabilidade de seu ambiente interno. Essa condição é denominada homeostase. A homeostase corresponde ao conjunto de mecanismos fisiológicos que regulam continuamente variáveis biológicas essenciais para a vida, como temperatura corporal, pressão arterial, frequência cardíaca, frequência respiratória, glicemia, equilíbrio hidroeletrolítico, pH sanguíneo e concentração de oxigênio nos tecidos.
Os organismos vivos são sistemas dinâmicos sujeitos a constantes perturbações internas e externas. Para garantir a sobrevivência, múltiplos mecanismos de controle atuam de forma integrada para manter essas variáveis dentro de limites fisiológicos compatíveis com o funcionamento adequado dos órgãos e sistemas. Quando esses mecanismos são eficazes, o organismo permanece em equilíbrio funcional; quando falham ou são sobrecarregados, surgem alterações fisiológicas que podem evoluir para estados patológicos.
Sob essa perspectiva, a doença pode ser entendida como uma disfunção dos mecanismos homeostáticos. Seja por agentes infecciosos, alterações genéticas, deficiências nutricionais, distúrbios metabólicos ou processos degenerativos, a doença manifesta-se frequentemente por alterações mensuráveis das funções vitais do organismo. Essas alterações podem produzir sintomas percebidos pelo paciente e sinais observáveis pelos profissionais de saúde.
Esses três indicadores representam dimensões complementares da homeostase:
Alterações na massa corporal podem influenciar tanto a frequência cardíaca quanto a pressão arterial média. O aumento da adiposidade, por exemplo, está frequentemente associado à ativação simpática, maior débito cardíaco e elevação da pressão arterial, enquanto a redução da massa corporal tende a diminuir a sobrecarga cardiovascular e melhorar a eficiência hemodinâmica. Dessa forma, a análise conjunta de FC, PAM e MCT fornece uma visão integrada do estado fisiológico e cardiovascular do indivíduo.
Os sinais vitais constituem, portanto, indicadores objetivos do estado funcional do organismo. Tradicionalmente incluem a pressão arterial, a frequência cardíaca, a frequência respiratória e a temperatura corporal. Atualmente, outros parâmetros são frequentemente incorporados à monitorização clínica, como a saturação periférica de oxigênio (SpO₂), a glicemia capilar e a pressão arterial média (PAM). Esses indicadores fornecem informações quantitativas sobre a capacidade do organismo de manter a homeostase e permitem identificar precocemente desvios fisiológicos associados a doenças agudas ou crônicas.
A monitorização sistemática dos sinais vitais desempenha papel central na avaliação clínica, no acompanhamento terapêutico e na prevenção de complicações. Em indivíduos saudáveis, esses parâmetros tendem a permanecer dentro de faixas fisiológicas relativamente estáveis. Em contrapartida, alterações persistentes ou abruptas podem indicar comprometimento dos mecanismos regulatórios do organismo, exigindo investigação diagnóstica e intervenção médica.
Dessa forma, o estudo dos sinais vitais representa uma aplicação prática do conceito de homeostase. A análise longitudinal dessas variáveis permite avaliar a dinâmica do equilíbrio fisiológico, identificar tendências, detectar mudanças estruturais ao longo do tempo e compreender como diferentes fatores biológicos, comportamentais e ambientais influenciam o estado de saúde dos indivíduos.
## =========================================================
## EXECUÇÃO: PrESsaO (sheet="PrESsaO")
## =========================================================
pkgs <- c(
"readxl","dplyr","ggplot2","forecast","KernSmooth","GGally","car",
"changepoint","strucchange","aTSA","trend","lmtest"
)
load_pkgs(pkgs)
safe_locale_ptbr()
df <- read_pressoes(params$xlsx_path, sheet = params$sheet_pressoes)
S <- make_series_pressoes(df)
cat("Paciente: JOS | ", date_range_str(S$dates), "\n")
## Paciente: JOS | Início: 2023-03-05 Fim: 2026-06-14
series4 <- cbind(S$SYS, S$DIA, S$FC, S$MCT)
colnames(series4) <- c("SYS","DIA","FC","MCT")
pairs_quick(series4)
## SYS DIA FC MCT
## SYS 1.00 0.74 -0.17 0.14
## DIA 0.74 1.00 -0.05 0.17
## FC -0.17 -0.05 1.00 -0.09
## MCT 0.14 0.17 -0.09 1.00
scatter_matrix(as.data.frame(series4))
plot_ts_multi(series4)
plot_ts_single(series4[,1:2])
PAM <- pam_your_formula(SYS = S$SYS, DIA = S$DIA, FC = S$FC)
pairs_quick(cbind(PAM = PAM, MCT = S$MCT))
## PAM MCT
## PAM 1.00 0.16
## MCT 0.16 1.00
## PAM (diagnóstico + plot calendário)
run_full_diagnostics(PAM)
## Created Using changepoint version 2.3
## Changepoint type : Change in mean
## Method of analysis : PELT
## Test Statistic : Normal
## Type of penalty : MBIC with value, 21.15037
## Minimum Segment Length : 1
## Maximum no. of cpts : Inf
## Number of changepoints: 409
## NULL
## Created Using changepoint version 2.3
## Changepoint type : Change in variance
## Method of analysis : PELT
## Test Statistic : Normal
## Type of penalty : MBIC with value, 21.15037
## Minimum Segment Length : 2
## Maximum no. of cpts : Inf
## Changepoint Locations :
## NULL
##
## Optimal 5-segment partition:
##
## Call:
## breakpoints.formula(formula = y ~ 1)
##
## Breakpoints at observation number:
## 195 384 556 953
##
## Corresponding to breakdates:
## 0.169124 0.3330442 0.4822203 0.8265395
##
## Approximate Cox-Stuart trend test
##
## data: y
## D+ = 316, p-value = 0.009815
## alternative hypothesis: data have a increasing trend
##
##
## Cox and Stuart Trend test
##
## data: y
## z = 0.18703, n = 1153, p-value = 0.8516
## alternative hypothesis: monotonic trend
##
##
## Mann-Kendall trend test
##
## data: y
## z = -0.96486, n = 1153, p-value = 0.3346
## alternative hypothesis: true S is not equal to 0
## sample estimates:
## S varS tau
## -1.260100e+04 1.705332e+08 -1.897528e-02
##
##
## Sen's slope
##
## data: y
## z = -0.96486, n = 1153, p-value = 0.3346
## alternative hypothesis: true z is not equal to 0
## 95 percent confidence interval:
## -0.0015429128 0.0005302837
## sample estimates:
## Sen's slope
## -0.0004996896
plot_series_with_changes_calendar(
dates = S$dates,
y = PAM,
main = paste0("Paciente: JOS | ", date_range_str(S$dates)),
ylab = "PAM",
hlines = c(70, 90, 100),
by = "3 months"
)
## MCT
run_full_diagnostics(S$MCT)
## Created Using changepoint version 2.3
## Changepoint type : Change in mean
## Method of analysis : PELT
## Test Statistic : Normal
## Type of penalty : MBIC with value, 21.15037
## Minimum Segment Length : 1
## Maximum no. of cpts : Inf
## Changepoint Locations : 12 50 133 188 286 529 640 772 918 966 1014
## NULL
## Created Using changepoint version 2.3
## Changepoint type : Change in variance
## Method of analysis : PELT
## Test Statistic : Normal
## Type of penalty : MBIC with value, 21.15037
## Minimum Segment Length : 2
## Maximum no. of cpts : Inf
## Changepoint Locations : 133 200 289 673
## NULL
##
## Optimal 5-segment partition:
##
## Call:
## breakpoints.formula(formula = y ~ 1)
##
## Breakpoints at observation number:
## 172 344 710 918
##
## Corresponding to breakdates:
## 0.1491761 0.2983521 0.6157849 0.7961839
##
## Approximate Cox-Stuart trend test
##
## data: y
## D+ = 303, p-value = 0.02872
## alternative hypothesis: data have a increasing trend
##
##
## Cox and Stuart Trend test
##
## data: y
## z = 10.899, n = 1153, p-value < 2.2e-16
## alternative hypothesis: monotonic trend
##
##
## Mann-Kendall trend test
##
## data: y
## z = -13.482, n = 1153, p-value < 2.2e-16
## alternative hypothesis: true S is not equal to 0
## sample estimates:
## S varS tau
## -1.760020e+05 1.704220e+08 -2.678129e-01
##
##
## Sen's slope
##
## data: y
## z = -13.482, n = 1153, p-value < 2.2e-16
## alternative hypothesis: true z is not equal to 0
## 95 percent confidence interval:
## -0.002913907 -0.002028986
## sample estimates:
## Sen's slope
## -0.002459016
plot_series_with_changes_calendar(
dates = S$dates,
y = S$MCT,
main = paste0("Paciente: JOS | ", date_range_str(S$dates)),
ylab = "MCT",
hlines = c(85),
by = "3 months"
)
## FC
run_full_diagnostics(S$FC)
## Created Using changepoint version 2.3
## Changepoint type : Change in mean
## Method of analysis : PELT
## Test Statistic : Normal
## Type of penalty : MBIC with value, 21.15037
## Minimum Segment Length : 1
## Maximum no. of cpts : Inf
## Number of changepoints: 524
## NULL
## Created Using changepoint version 2.3
## Changepoint type : Change in variance
## Method of analysis : PELT
## Test Statistic : Normal
## Type of penalty : MBIC with value, 21.15037
## Minimum Segment Length : 2
## Maximum no. of cpts : Inf
## Changepoint Locations : 507 600 956 999
## NULL
##
## Optimal 3-segment partition:
##
## Call:
## breakpoints.formula(formula = y ~ 1)
##
## Breakpoints at observation number:
## 173 598
##
## Corresponding to breakdates:
## 0.1500434 0.518647
## $index
## [1] 596 1037
##
## $values
## [1] 118 107
##
## $raw
## $raw$index
## [1] 596 1037
##
## $raw$replacements
## [1] 85.5 83.0
##
##
##
## Approximate Cox-Stuart trend test
##
## data: y
## D+ = 364, p-value = 1.041e-13
## alternative hypothesis: data have a increasing trend
##
##
## Cox and Stuart Trend test
##
## data: y
## z = 4.9819, n = 1153, p-value = 6.297e-07
## alternative hypothesis: monotonic trend
##
##
## Mann-Kendall trend test
##
## data: y
## z = -7.4004, n = 1153, p-value = 1.357e-13
## alternative hypothesis: true S is not equal to 0
## sample estimates:
## S varS tau
## -9.654600e+04 1.701941e+08 -1.483238e-01
##
##
## Sen's slope
##
## data: y
## z = -7.4004, n = 1153, p-value = 1.357e-13
## alternative hypothesis: true z is not equal to 0
## 95 percent confidence interval:
## -0.005836576 -0.003325942
## sample estimates:
## Sen's slope
## -0.004580153
plot_series_with_changes_calendar(
dates = S$dates,
y = S$FC,
main = paste0("Paciente: JOS | ", date_range_str(S$dates)),
ylab = "FC",
hlines = c(60, 80, 100),
by = "3 months"
)
## ARIMAX (exemplo)
cat("Normalidade (Shapiro):\n")
## Normalidade (Shapiro):
print(shapiro.test(as.numeric(PAM)))
##
## Shapiro-Wilk normality test
##
## data: as.numeric(PAM)
## W = 0.99767, p-value = 0.1009
print(shapiro.test(as.numeric(S$MCT)))
##
## Shapiro-Wilk normality test
##
## data: as.numeric(S$MCT)
## W = 0.80457, p-value < 2.2e-16
res_arimax <- fit_arimax(
y = as.numeric(PAM),
xreg = cbind(MCT = as.numeric(S$MCT)),
lambda = 0
)
##
## Fitting models using approximations to speed things up...
##
## Regression with ARIMA(2,0,2) errors : Inf
## Regression with ARIMA(0,0,0) errors : -3007.646
## Regression with ARIMA(1,0,0) errors : -3084.085
## Regression with ARIMA(0,0,1) errors : -3064.123
## Regression with ARIMA(0,0,0) errors : -1399.47
## Regression with ARIMA(2,0,0) errors : -3114.524
## Regression with ARIMA(3,0,0) errors : -3117.966
## Regression with ARIMA(4,0,0) errors : -3128.164
## Regression with ARIMA(5,0,0) errors : -3144.104
## Regression with ARIMA(5,0,1) errors : -3153.823
## Regression with ARIMA(4,0,1) errors : -3154.566
## Regression with ARIMA(3,0,1) errors : -3152.357
## Regression with ARIMA(4,0,2) errors : Inf
## Regression with ARIMA(3,0,2) errors : -3151.294
## Regression with ARIMA(5,0,2) errors : -3151.822
## Regression with ARIMA(4,0,1) errors : -2961.357
##
## Now re-fitting the best model(s) without approximations...
##
## Regression with ARIMA(4,0,1) errors : -3157.552
##
## Best model: Regression with ARIMA(4,0,1) errors
print(res_arimax$summary)
## Series: y
## Regression with ARIMA(4,0,1) errors
## Box Cox transformation: lambda= 0
##
## Coefficients:
## ar1 ar2 ar3 ar4 ma1 intercept MCT
## 0.8993 -0.0102 -0.0597 0.0780 -0.7330 4.0030 0.0054
## s.e. 0.0730 0.0414 0.0405 0.0346 0.0682 0.1553 0.0018
##
## sigma^2 = 0.003755: log likelihood = 1586.84
## AIC=-3157.68 AICc=-3157.55 BIC=-3117.28
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE
## Training set 0.1577777 5.293355 4.169381 -0.1910768 4.820878 0.7664638
## ACF1
## Training set -0.00689067
print(res_arimax$coeftest)
##
## z test of coefficients:
##
## Estimate Std. Error z value Pr(>|z|)
## ar1 0.8993123 0.0729949 12.3202 < 2.2e-16 ***
## ar2 -0.0101882 0.0413821 -0.2462 0.805528
## ar3 -0.0596912 0.0404691 -1.4750 0.140217
## ar4 0.0779701 0.0345530 2.2565 0.024037 *
## ma1 -0.7329597 0.0682470 -10.7398 < 2.2e-16 ***
## intercept 4.0029575 0.1552597 25.7823 < 2.2e-16 ***
## MCT 0.0053669 0.0018138 2.9590 0.003087 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
print(res_arimax$box_p)
## [1] 0.9307619
## =========================================================
## EXECUÇÃO: MAPA (sheet="MAPA") com eixo hora (15 em 15 min)
## =========================================================
load_pkgs(c("readxl","dplyr","GGally","car","forecast","KernSmooth"))
df_mapa <- readxl::read_excel(params$xlsx_path, sheet = params$sheet_mapa)
stop_if_missing(df_mapa, c("HORA","PAS","PAD","PAM","MAPA","PAM13","FC"))
df_mapa <- df_mapa |>
dplyr::mutate(
HORA = as.POSIXct(HORA, tz = "America/Sao_Paulo"),
PAS = as.numeric(PAS),
PAD = as.numeric(PAD),
PAM = as.numeric(PAM),
MAPA = as.numeric(MAPA),
PAM13 = as.numeric(PAM13),
FC = as.numeric(FC)
) |>
dplyr::filter(is.finite(HORA)) |>
dplyr::arrange(HORA) |>
dplyr::group_by(HORA) |>
dplyr::summarise(
PAS = mean(PAS, na.rm = TRUE),
PAD = mean(PAD, na.rm = TRUE),
PAM = mean(PAM, na.rm = TRUE),
MAPA = mean(MAPA, na.rm = TRUE),
PAM13 = mean(PAM13, na.rm = TRUE),
FC = mean(FC, na.rm = TRUE),
.groups = "drop"
)
## índice 15 em 15 min (eixo que você quer)
t15 <- seq_len(nrow(df_mapa))
## ---- exploratório: correlação + pares
X1 <- df_mapa[, c("PAS","PAD","FC")]
X2 <- df_mapa[, c("PAM","MAPA","PAM13")]
print(round(cor(X1, use = "pairwise.complete.obs"), 2))
## PAS PAD FC
## PAS 1.00 0.68 -0.02
## PAD 0.68 1.00 0.10
## FC -0.02 0.10 1.00
print(round(cor(X2, use = "pairwise.complete.obs"), 2))
## PAM MAPA PAM13
## PAM 1.00 0.99 0.99
## MAPA 0.99 1.00 0.99
## PAM13 0.99 0.99 1.00
print(GGally::ggpairs(X1, title = "", diag = list(continuous = "densityDiag")))
print(GGally::ggpairs(X2, title = "", diag = list(continuous = "densityDiag")))
car::scatterplotMatrix(as.data.frame(df_mapa[, c("PAS","PAD","FC","PAM","MAPA","PAM13")]),
smooth = FALSE,
regLine = TRUE,
lower.panel = NULL,
ellipse = list(levels = c(0.68), robust = TRUE, fill = FALSE),
col = "gray45",
cex = 0.2,
pch = 1,
main = "")
## ---- utilitários de plot robusto em eixo t15
break_on_gap_time <- function(dates, y, gap_mins = 60) {
o <- order(dates)
dates <- dates[o]
y <- as.numeric(y)[o]
dx <- c(0, diff(as.numeric(dates))) # segundos
y_line <- y
y_line[dx > gap_mins * 60] <- NA_real_ # quebra linhas em gaps grandes
list(dates = dates, y = y, y_line = y_line, o = o)
}
locpoly_smooth_x <- function(x, y) {
x <- as.numeric(x)
y <- as.numeric(y)
ok <- is.finite(x) & is.finite(y)
x <- x[ok]; y <- y[ok]
if (length(y) < 10) return(rep(NA_real_, length(ok)))
o <- order(x)
x <- x[o]; y <- y[o]
n <- length(y)
bw <- suppressWarnings(KernSmooth::dpill(x, y, gridsize = n))
if (!is.finite(bw) || bw <= 0) {
rng <- diff(range(x))
bw <- if (is.finite(rng) && rng > 0) rng/20 else 1
}
lp <- KernSmooth::locpoly(x, y, bandwidth = bw, gridsize = n)
stats::approx(lp$x, lp$y, xout = x, rule = 2)$y
}
plot_15min <- function(dates, y, main, ylab,
hlines = NULL,
vlines = NULL,
gap_mins = 60,
show_smooth = TRUE) {
b <- break_on_gap_time(dates, y, gap_mins = gap_mins)
## x = índice 15-min após ordenação
x <- seq_along(b$dates)
plot(x, b$y, type = "p", cex = 0.5,
main = main, xlab = "Hora (15 em 15 min)", ylab = ylab,
col = "black")
lines(x, b$y_line, col = "gray")
if (!is.null(hlines)) for (h in hlines) abline(h = h, lty = 2)
if (!is.null(vlines)) for (v in vlines) abline(v = v, lty = 3)
if (show_smooth) {
sm <- locpoly_smooth_x(x, b$y)
if (any(is.finite(sm))) lines(x, sm, lwd = 1.5)
}
invisible(TRUE)
}
## ---- gráficos pedidos: PAM e FC em 15/15
plot_15min(df_mapa$HORA, df_mapa$PAM,
main = "MAPA do Paciente: JOS\nData: 20/01/2023",
ylab = "PAM",
hlines = c(70, 90, 100),
vlines = c(24, 36, 68),
gap_mins = 60)
plot_15min(df_mapa$HORA, df_mapa$FC,
main = "MAPA do Paciente: JOS\nData: 20/01/2023",
ylab = "FC",
hlines = c(60, 100),
vlines = c(24, 36, 68),
gap_mins = 60)
## ---- comparação no mesmo painel: PAM vs MAPA vs PAM13
o <- order(df_mapa$HORA)
x <- seq_along(o)
plot(x, df_mapa$PAM[o], type = "p", cex = 0.5,
main = "MAPA do Paciente: JOS\nComparação: PAM vs MAPA vs PAM13",
xlab = "Hora (15 em 15 min)", ylab = "mmHg", col = "black")
lines(x, df_mapa$PAM[o], col = "gray")
points(x, df_mapa$MAPA[o], pch = 1, cex = 0.5, col = "black")
lines(x, df_mapa$MAPA[o], col = "gray")
points(x, df_mapa$PAM13[o], pch = 2, cex = 0.5, col = "black")
lines(x, df_mapa$PAM13[o], col = "gray")
abline(h = c(70, 90, 100), lty = 2)
legend("topright",
legend = c("PAM","MAPA","PAM13"),
pch = c(1,1,2),
bty = "n")