As medidas de referência foram obtidas utilizando dispositivos eletrônicos comerciais destinados ao monitoramento domiciliar de parâmetros fisiológicos, metabólicos e antropométricos. A pressão arterial sistólica (PAS), pressão arterial diastólica (PAD) e frequência cardíaca (FC) foram medidas por meio de um monitor automático de braço Omron HEM-7346T (Omron Healthcare Co., Kyoto, Japão), equipado com tecnologia Bluetooth para armazenamento e transferência dos dados.
A massa corporal total (MCT) e a composição corporal foram obtidas utilizando uma balança de bioimpedância Omron HBF-222T (Omron Healthcare Co., Kyoto, Japão). A temperatura corporal foi medida com um termômetro digital G-Tech TH-186 (Accumed-Glicomed, Duque de Caxias, RJ, Brasil). A saturação periférica de oxigênio (SpO₂) e a frequência cardíaca também foram avaliadas por um oxímetro de pulso de dedo Multilaser Saúde HC261 (Multilaser Industrial S.A., Extrema, MG, Brasil).
A glicose intersticial foi monitorada continuamente por meio do sistema FreeStyle Libre (Abbott Diabetes Care Inc., Alameda, CA, EUA), um sensor de monitorização contínua da glicose (CGM) aplicado na região posterior do braço, capaz de registrar automaticamente as concentrações de glicose ao longo do dia sem necessidade de punções digitais rotineiras.
As medidas obtidas pelos dispositivos de referência foram comparadas às fornecidas por dispositivos vestíveis da Samsung Electronics Co. (Suwon, Coreia do Sul), incluindo smartwatch Galaxy Watch e pulseira Galaxy Fit. As variáveis avaliadas compreenderam frequência cardíaca, saturação periférica de oxigênio, massa corporal total, percentual de gordura corporal e demais parâmetros fisiológicos disponibilizados pelos dispositivos.
Todos os equipamentos foram utilizados de acordo com as instruções dos fabricantes. As medições foram realizadas em ambiente domiciliar durante o período de acompanhamento longitudinal do participante. Os dispositivos Omron, G-Tech, Multilaser e FreeStyle Libre foram considerados métodos de referência para fins de comparação e avaliação de equivalência metrológica dos dispositivos vestíveis.
A equivalência entre os métodos foi investigada por meio da abordagem estrutural implementada no pacote eirasAgree, baseada na avaliação sequencial de viés estrutural, precisão estrutural e concordância estrutural.
Analisar as variáveis digitais:
Temperatura, SpO2_WTC,
SpO2_ML, PI_ML, FC_ML,
FC_WTC, FC_Gfit, FR_Gfit,
Glicemia, MCT_ML,
GorduraCorp_WTC.
A análise usa apenas a janela temporal em que há pelo menos uma variável digital observada.
As comparações de equivalência de métodos são feitas diretamente com
eirasagree::AllStructuralTests(), sem reimplementar o
método:
Pulso(bpm) como referência para FC_ML,
FC_WTC e FC_Gfit;Peso(kg) como referência para MCT_ML;Gordura corporal(%) como referência para
GorduraCorp_WTC.As demais variáveis digitais são analisadas por descrição, gráficos temporais e associação com FC, MCT e gordura corporal da balança.
load_pkgs <- function(pkgs) {
for (p in pkgs) {
if (!requireNamespace(p, quietly = TRUE)) {
stop("Pacote ausente: ", p, ". Instale com install.packages('", p, "') ou conforme documentação do pacote.")
}
suppressPackageStartupMessages(library(p, character.only = TRUE))
}
invisible(TRUE)
}
safe_locale_ptbr <- function() {
suppressWarnings(try(Sys.setlocale("LC_ALL", "pt_BR.UTF-8"), silent = TRUE))
invisible(TRUE)
}
as_num <- function(x) {
suppressWarnings(as.numeric(x))
}
stop_if_missing <- function(df, vars) {
miss <- setdiff(vars, names(df))
if (length(miss) > 0) stop("Colunas ausentes: ", paste(miss, collapse = ", "))
invisible(TRUE)
}
date_range_str <- function(d) {
d <- as.Date(d)
d <- d[is.finite(d)]
if (length(d) == 0) return(NA_character_)
paste0("Início: ", format(min(d), "%Y-%m-%d"), " Fim: ", format(max(d), "%Y-%m-%d"))
}
axis_month_year <- function(dates, by = "1 month") {
dates <- as.Date(dates)
dates <- dates[is.finite(dates)]
if (length(dates) == 0) return(invisible(NULL))
at <- seq(from = as.Date(cut(min(dates), "month")),
to = as.Date(cut(max(dates), "month")),
by = by)
axis(1, at = at, labels = format(at, "%m/%y"), las = 2, cex.axis = 0.8)
invisible(at)
}
plot_calendar_var <- function(df, date_col, y_col, main = NULL, ylab = NULL,
by = "1 month", hlines = NULL, show_smooth = TRUE) {
stop_if_missing(df, c(date_col, y_col))
d <- as.Date(df[[date_col]])
y <- as_num(df[[y_col]])
ok <- is.finite(d) & is.finite(y)
d <- d[ok]
y <- y[ok]
if (length(y) < 1) {
plot.new()
title(main = paste0(y_col, ": sem dados"))
return(invisible(NULL))
}
o <- order(d)
d <- d[o]
y <- y[o]
if (is.null(main)) main <- paste0("Paciente: JOS | ", y_col)
if (is.null(ylab)) ylab <- y_col
yl <- range(y, na.rm = TRUE)
if (diff(yl) == 0) yl <- yl + c(-1, 1)
plot(d, y, type = "p", cex = 0.55, xaxt = "n", xlim = range(d), ylim = yl,
main = main, xlab = "Mês/Ano", ylab = ylab, col = "black")
lines(d, y, col = "gray")
axis_month_year(d, by = by)
if (!is.null(hlines)) {
for (h in hlines) abline(h = h, lty = 2)
}
if (show_smooth && length(y) >= 10) {
x <- seq_along(y)
bw <- suppressWarnings(KernSmooth::dpill(x, y, gridsize = length(y)))
if (!is.finite(bw) || bw <= 0) bw <- max(1, length(y) / 20)
lp <- KernSmooth::locpoly(x, y, bandwidth = bw, gridsize = length(y))
sm <- stats::approx(lp$x, lp$y, xout = x, rule = 2)$y
lines(d, sm, lwd = 1.5)
}
invisible(data.frame(Data = d, y = y))
}
round_numeric <- function(df, digits = 4) {
out <- as.data.frame(df)
num <- vapply(out, is.numeric, logical(1))
out[num] <- lapply(out[num], round, digits = digits)
out
}
summary_numeric <- function(df, vars) {
out <- data.frame(
variavel = character(0),
n = integer(0),
media = numeric(0),
dp = numeric(0),
mediana = numeric(0),
q1 = numeric(0),
q3 = numeric(0),
minimo = numeric(0),
maximo = numeric(0)
)
for (v in vars) {
y <- as_num(df[[v]])
y <- y[is.finite(y)]
if (length(y) == 0) {
linha <- data.frame(variavel = v, n = 0, media = NA, dp = NA, mediana = NA,
q1 = NA, q3 = NA, minimo = NA, maximo = NA)
} else {
linha <- data.frame(
variavel = v,
n = length(y),
media = mean(y),
dp = stats::sd(y),
mediana = stats::median(y),
q1 = as.numeric(stats::quantile(y, 0.25, na.rm = TRUE)),
q3 = as.numeric(stats::quantile(y, 0.75, na.rm = TRUE)),
minimo = min(y),
maximo = max(y)
)
}
out <- rbind(out, linha)
}
out
}
cor_pair_table <- function(df, y_vars, x_vars) {
out <- data.frame(
y = character(0),
x = character(0),
n = integer(0),
pearson = numeric(0),
spearman = numeric(0),
p_pearson = numeric(0),
p_spearman = numeric(0)
)
for (yv in y_vars) {
for (xv in x_vars) {
y <- as_num(df[[yv]])
x <- as_num(df[[xv]])
ok <- is.finite(x) & is.finite(y)
n <- sum(ok)
if (n >= 4) {
ct1 <- suppressWarnings(stats::cor.test(x[ok], y[ok], method = "pearson"))
ct2 <- suppressWarnings(stats::cor.test(x[ok], y[ok], method = "spearman", exact = FALSE))
linha <- data.frame(y = yv, x = xv, n = n,
pearson = unname(ct1$estimate),
spearman = unname(ct2$estimate),
p_pearson = ct1$p.value,
p_spearman = ct2$p.value)
} else {
linha <- data.frame(y = yv, x = xv, n = n,
pearson = NA, spearman = NA,
p_pearson = NA, p_spearman = NA)
}
out <- rbind(out, linha)
}
}
out
}
scatter_ref <- function(df, y_col, x_col, main = NULL) {
y <- as_num(df[[y_col]])
x <- as_num(df[[x_col]])
ok <- is.finite(x) & is.finite(y)
if (sum(ok) < 3) {
plot.new()
title(main = paste0(y_col, " vs ", x_col, ": dados insuficientes"))
return(invisible(NULL))
}
if (is.null(main)) main <- paste0(y_col, " vs ", x_col)
plot(x[ok], y[ok], pch = 1, cex = 0.65, col = "black",
xlab = x_col, ylab = y_col, main = main)
abline(stats::lm(y[ok] ~ x[ok]), lty = 1)
invisible(TRUE)
}
make_eiras_data <- function(df, reference_col, newmethod_col) {
stop_if_missing(df, c(reference_col, newmethod_col))
x <- as_num(df[[reference_col]])
y <- as_num(df[[newmethod_col]])
ok <- is.finite(x) & is.finite(y)
out <- data.frame(Referencia = x[ok], NovoMetodo = y[ok])
## Nomes simples evitam erro de arquivos gerados pelo eirasagree
## com caracteres especiais, como %, parênteses e acentos.
out
}
safe_file_label <- function(x) {
x <- iconv(x, from = "", to = "ASCII//TRANSLIT")
x <- gsub("[^A-Za-z0-9]+", "_", x)
x <- gsub("^_+|_+$", "", x)
x
}
run_eirasagree_pair <- function(df, reference_col, newmethod_col,
alpha = 0.05, out.format = "html") {
dat <- make_eiras_data(df, reference_col, newmethod_col)
cat("\n\nComparação estrutural: ", newmethod_col, " vs ", reference_col, " \n", sep = "")
cat("n pares completos: ", nrow(dat), " \n", sep = "")
if (nrow(dat) < 5) {
cat("Dados insuficientes para comparação estrutural.\n")
return(invisible(NULL))
}
subdir <- paste0(safe_file_label(newmethod_col), "_vs_", safe_file_label(reference_col))
outdir <- file.path("eirasagree_outputs", subdir)
dir.create(outdir, recursive = TRUE, showWarnings = FALSE)
oldwd <- getwd()
setwd(outdir)
zz <- file("console_eirasagree.txt", open = "wt")
sink(zz)
sink(zz, type = "message")
out <- NULL
erro <- NULL
tryCatch(
{
out <- eirasagree::AllStructuralTests(
dat,
reference.cols = 1,
newmethod.cols = 2,
alpha = alpha,
out.format = out.format
)
},
error = function(e) {
erro <<- e
}
)
sink(type = "message")
sink()
close(zz)
setwd(oldwd)
if (!is.null(erro)) {
stop("Erro em eirasagree::AllStructuralTests para ",
newmethod_col, " vs ", reference_col, ": ", conditionMessage(erro))
}
html_file <- file.path(outdir, "Referencia_and_NovoMetodo.html")
console_file <- file.path(outdir, "console_eirasagree.txt")
if (file.exists(html_file)) {
cat("Relatório HTML: [abrir resultado](", html_file, ") \n", sep = "")
} else {
cat("Relatório HTML não localizado. Ver console: [console_eirasagree.txt](", console_file, ") \n", sep = "")
}
invisible(out)
}
pkgs <- c("readxl", "dplyr", "knitr", "KernSmooth", "GGally", "eirasagree")
load_pkgs(pkgs)
safe_locale_ptbr()
df0 <- readxl::read_excel(params$xlsx_path, sheet = params$sheet_pressoes)
vars_digitais <- c(
"Temperatura",
"SpO2_WTC",
"SpO2_ML",
"PI_ML",
"FC_ML",
"FC_WTC",
"FC_Gfit",
"FR_Gfit",
"Glicemia",
"MCT_ML",
"GorduraCorp_WTC"
)
vars_referencia <- c(
"Pulso(bpm)",
"Peso(kg)",
"Gordura corporal(%)"
)
stop_if_missing(df0, c("Data da medição", vars_digitais, vars_referencia))
df <- as.data.frame(df0)
df[["Data da medição"]] <- as.POSIXct(df[["Data da medição"]], tz = "America/Sao_Paulo")
for (v in c(vars_digitais, vars_referencia)) {
df[[v]] <- as_num(df[[v]])
}
linhas_digitais <- rowSums(!is.na(df[, vars_digitais, drop = FALSE])) > 0
df_digital <- df[linhas_digitais, , drop = FALSE]
df_digital <- df_digital[order(df_digital[["Data da medição"]]), , drop = FALSE]
cat("Janela digital | ", date_range_str(df_digital[["Data da medição"]]), "\n")
## Janela digital | Início: 2023-10-22 Fim: 2024-02-01
cat("n linhas na janela digital:", nrow(df_digital), "\n")
## n linhas na janela digital: 98
resumo <- summary_numeric(df_digital, c(vars_digitais, vars_referencia))
knitr::kable(round_numeric(resumo, 4), caption = "Resumo descritivo na janela temporal digital")
| variavel | n | media | dp | mediana | q1 | q3 | minimo | maximo |
|---|---|---|---|---|---|---|---|---|
| Temperatura | 98 | 35.6143 | 0.2577 | 35.60 | 35.400 | 35.800 | 34.9 | 36.2 |
| SpO2_WTC | 86 | 93.7674 | 2.5607 | 94.00 | 92.000 | 95.750 | 90.0 | 100.0 |
| SpO2_ML | 90 | 96.4778 | 1.2382 | 96.00 | 96.000 | 98.000 | 94.0 | 99.0 |
| PI_ML | 90 | 1009.1678 | 6690.4728 | 6.35 | 4.600 | 7.900 | 1.3 | 45142.0 |
| FC_ML | 90 | 78.3111 | 5.9806 | 78.00 | 74.000 | 82.750 | 66.0 | 94.0 |
| FC_WTC | 89 | 83.0449 | 6.8853 | 82.00 | 79.000 | 87.000 | 70.0 | 101.0 |
| FC_Gfit | 85 | 79.8118 | 6.8112 | 80.00 | 75.000 | 85.000 | 64.0 | 99.0 |
| FR_Gfit | 86 | 16.1977 | 1.6579 | 16.00 | 15.000 | 17.000 | 13.0 | 20.0 |
| Glicemia | 28 | 99.5000 | 5.7252 | 99.50 | 94.750 | 102.750 | 89.0 | 113.0 |
| MCT_ML | 81 | 85.7370 | 0.6972 | 85.70 | 85.300 | 86.200 | 83.6 | 87.3 |
| GorduraCorp_WTC | 79 | 29.0114 | 0.8419 | 29.10 | 28.700 | 29.600 | 26.1 | 30.5 |
| Pulso(bpm) | 98 | 80.5612 | 7.4930 | 81.00 | 74.000 | 85.000 | 68.0 | 105.0 |
| Peso(kg) | 98 | 85.2429 | 0.7355 | 85.20 | 84.800 | 85.675 | 83.3 | 87.1 |
| Gordura corporal(%) | 98 | 28.8194 | 0.3366 | 28.90 | 28.625 | 29.075 | 28.0 | 29.6 |
Cada gráfico usa apenas as datas em que a própria variável tem valor observado. Isso evita eixo temporal artificialmente longo.
for (v in vars_digitais) {
plot_calendar_var(
df = df_digital,
date_col = "Data da medição",
y_col = v,
main = paste0("Paciente: JOS | ", v),
ylab = v,
by = "1 month"
)
}
cor_tab <- cor_pair_table(
df = df_digital,
y_vars = vars_digitais,
x_vars = vars_referencia
)
knitr::kable(round_numeric(cor_tab, 4), caption = "Correlação das variáveis digitais com FC, MCT e gordura corporal da balança")
| y | x | n | pearson | spearman | p_pearson | p_spearman |
|---|---|---|---|---|---|---|
| Temperatura | Pulso(bpm) | 98 | 0.3317 | 0.2898 | 0.0008 | 0.0038 |
| Temperatura | Peso(kg) | 98 | -0.2366 | -0.2288 | 0.0190 | 0.0234 |
| Temperatura | Gordura corporal(%) | 98 | -0.2017 | -0.2035 | 0.0464 | 0.0445 |
| SpO2_WTC | Pulso(bpm) | 86 | 0.0192 | 0.0257 | 0.8609 | 0.8140 |
| SpO2_WTC | Peso(kg) | 86 | 0.1835 | 0.2357 | 0.0908 | 0.0289 |
| SpO2_WTC | Gordura corporal(%) | 86 | 0.0694 | 0.1532 | 0.5255 | 0.1591 |
| SpO2_ML | Pulso(bpm) | 90 | -0.3842 | -0.3740 | 0.0002 | 0.0003 |
| SpO2_ML | Peso(kg) | 90 | 0.2809 | 0.2762 | 0.0073 | 0.0084 |
| SpO2_ML | Gordura corporal(%) | 90 | 0.2688 | 0.2774 | 0.0104 | 0.0081 |
| PI_ML | Pulso(bpm) | 90 | -0.0564 | 0.3502 | 0.5975 | 0.0007 |
| PI_ML | Peso(kg) | 90 | 0.1827 | -0.0084 | 0.0847 | 0.9377 |
| PI_ML | Gordura corporal(%) | 90 | 0.1558 | -0.0168 | 0.1424 | 0.8753 |
| FC_ML | Pulso(bpm) | 90 | 0.7416 | 0.6960 | 0.0000 | 0.0000 |
| FC_ML | Peso(kg) | 90 | -0.2202 | -0.1862 | 0.0371 | 0.0789 |
| FC_ML | Gordura corporal(%) | 90 | -0.2006 | -0.1862 | 0.0580 | 0.0789 |
| FC_WTC | Pulso(bpm) | 89 | 0.5301 | 0.5389 | 0.0000 | 0.0000 |
| FC_WTC | Peso(kg) | 89 | -0.0315 | -0.0782 | 0.7696 | 0.4663 |
| FC_WTC | Gordura corporal(%) | 89 | -0.1016 | -0.1226 | 0.3434 | 0.2525 |
| FC_Gfit | Pulso(bpm) | 85 | 0.6742 | 0.6079 | 0.0000 | 0.0000 |
| FC_Gfit | Peso(kg) | 85 | -0.2624 | -0.2525 | 0.0152 | 0.0198 |
| FC_Gfit | Gordura corporal(%) | 85 | -0.2621 | -0.2581 | 0.0154 | 0.0171 |
| FR_Gfit | Pulso(bpm) | 86 | 0.0891 | 0.0540 | 0.4144 | 0.6217 |
| FR_Gfit | Peso(kg) | 86 | -0.4480 | -0.4280 | 0.0000 | 0.0000 |
| FR_Gfit | Gordura corporal(%) | 86 | -0.4230 | -0.4448 | 0.0000 | 0.0000 |
| Glicemia | Pulso(bpm) | 28 | -0.0121 | -0.0629 | 0.9514 | 0.7506 |
| Glicemia | Peso(kg) | 28 | 0.1015 | 0.0967 | 0.6072 | 0.6245 |
| Glicemia | Gordura corporal(%) | 28 | 0.1128 | 0.1147 | 0.5675 | 0.5610 |
| MCT_ML | Pulso(bpm) | 81 | -0.1836 | -0.1485 | 0.1009 | 0.1858 |
| MCT_ML | Peso(kg) | 81 | 0.8744 | 0.8827 | 0.0000 | 0.0000 |
| MCT_ML | Gordura corporal(%) | 81 | 0.7882 | 0.7994 | 0.0000 | 0.0000 |
| GorduraCorp_WTC | Pulso(bpm) | 79 | -0.2953 | -0.3261 | 0.0082 | 0.0034 |
| GorduraCorp_WTC | Peso(kg) | 79 | -0.0516 | -0.0428 | 0.6514 | 0.7080 |
| GorduraCorp_WTC | Gordura corporal(%) | 79 | -0.0408 | -0.0005 | 0.7214 | 0.9964 |
vars_pair <- c(vars_digitais, vars_referencia)
vars_pair <- vars_pair[vars_pair %in% names(df_digital)]
ok_n <- sapply(vars_pair, function(v) sum(is.finite(as_num(df_digital[[v]]))))
vars_pair <- vars_pair[ok_n >= 3]
if (length(vars_pair) >= 2) {
print(GGally::ggpairs(
df_digital[, vars_pair, drop = FALSE],
title = "Variáveis digitais e referências da balança",
diag = list(continuous = "densityDiag")
))
}
for (v in vars_digitais) {
scatter_ref(df_digital, y_col = v, x_col = "Pulso(bpm)")
scatter_ref(df_digital, y_col = v, x_col = "Peso(kg)")
scatter_ref(df_digital, y_col = v, x_col = "Gordura corporal(%)")
}
Método aplicado diretamente por
eirasagree::AllStructuralTests().
Apenas pares que medem o mesmo construto são submetidos à comparação estrutural:
Comparação estrutural: FC_ML vs Pulso(bpm)
n pares completos: 90
Relatório HTML não localizado. Ver console: console_eirasagree.txt
Comparação estrutural: FC_WTC vs Pulso(bpm)
n pares completos: 89
Relatório HTML não localizado. Ver console: console_eirasagree.txt
Comparação estrutural: FC_Gfit vs Pulso(bpm)
n pares completos: 85
Relatório HTML não localizado. Ver console: console_eirasagree.txt
Comparação estrutural: SpO2_ML vs SpO2_WTC
n pares completos: 86
Relatório HTML não localizado. Ver console: console_eirasagree.txt
Comparação estrutural: MCT_ML vs Peso(kg)
n pares completos: 81
Relatório HTML não localizado. Ver console: console_eirasagree.txt
Comparação estrutural: GorduraCorp_WTC vs Gordura corporal(%)
n pares completos: 79
Relatório HTML não localizado. Ver console: console_eirasagree.txt
O procedimento clássico de Bland-Altman não foi usado como critério
decisório. A equivalência entre métodos foi avaliada pelo procedimento
estrutural do pacote eirasagree, com decomposição em
acurácia, precisão e concordância com a bissetriz.
Para variáveis que não medem o mesmo construto da balança, como
Temperatura, PI_ML, FR_Gfit e
Glicemia, não há comparação de método contra FC, MCT ou
gordura corporal. SpO2_WTC e SpO2_ML medem o
mesmo construto e, por isso, foram comparadas por
eirasagree::AllStructuralTests().
A equivalência entre os dispositivos vestíveis e os respectivos métodos de referência foi avaliada utilizando a abordagem estrutural implementada no pacote eirasAgree. A análise foi conduzida em três níveis complementares: viés estrutural (acurácia), precisão estrutural e concordância estrutural.
A frequência cardíaca medida pelo Galaxy Fit apresentou ausência de viés estrutural, manutenção da precisão estrutural e concordância estrutural compatível com a reta identidade. Esse foi o único dispositivo que satisfez simultaneamente todos os critérios de equivalência.
A frequência cardíaca medida pelo oxímetro Multilaser apresentou viés estrutural negativo e perda de precisão estrutural em relação ao monitor Omron, embora a hipótese de concordância estrutural não tenha sido rejeitada.
A frequência cardíaca medida pelo Galaxy Watch apresentou viés estrutural positivo em relação ao monitor Omron. Apesar da manutenção da precisão estrutural e da concordância estrutural, a presença de viés impediu a demonstração de equivalência.
A estimativa de gordura corporal fornecida pelo Galaxy Watch apresentou viés estrutural positivo e perda de precisão estrutural em relação à balança Omron HBF-222T.
A massa corporal total medida pela balança Multilaser apresentou viés estrutural positivo em relação à balança Omron HBF-222T, embora a precisão estrutural tenha sido preservada.
A saturação periférica de oxigênio medida pelo Galaxy Watch apresentou viés estrutural positivo e perda de precisão estrutural em relação ao oxímetro Multilaser HC261.
Os resultados demonstraram que a frequência cardíaca obtida pelo Galaxy Fit foi a única variável que apresentou evidência simultânea de ausência de viés estrutural, manutenção da precisão estrutural e concordância estrutural com o método de referência.
Os demais dispositivos apresentaram evidência de viés estrutural, perda de precisão estrutural ou ambos. Embora a hipótese de concordância estrutural não tenha sido rejeitada em nenhuma das comparações, a presença de viés e/ou perda de precisão impede a caracterização de equivalência metrológica.
Esses resultados evidenciam que a concordância estrutural, isoladamente, não é suficiente para demonstrar equivalência entre métodos de medida. A equivalência requer simultaneamente ausência de viés estrutural, manutenção da precisão estrutural e compatibilidade com a reta identidade.
| Variável | Método novo | Método de referência | Diferença média (Novo − Referência) | IC95% do viés | Viés estrutural | Precisão estrutural | Concordância estrutural |
|---|---|---|---|---|---|---|---|
| Frequência cardíaca (bpm) | Galaxy Fit | Omron HEM-7346T | -0,46 | -1,77 a 0,77 | Não rejeitado | Não rejeitada | Não rejeitada |
| Frequência cardíaca (bpm) | Oxímetro Multilaser HC261 | Omron HEM-7346T | -2,00 | -2,92 a -1,08 | Rejeitado | Rejeitada | Não rejeitada |
| Frequência cardíaca (bpm) | Galaxy Watch | Omron HEM-7346T | +2,75 | 1,36 a 4,11 | Rejeitado | Não rejeitada | Não rejeitada |
| Gordura corporal (%) | Galaxy Watch | Omron HBF-222T | +0,26 | 0,03 a 0,46 | Rejeitado | Rejeitada | Não rejeitada |
| Massa corporal total (kg) | Balança Multilaser | Omron HBF-222T | +0,60 | 0,52 a 0,68 | Rejeitado | Não rejeitada | Não rejeitada |
| Saturação periférica de oxigênio (%) | Galaxy Watch | Oxímetro Multilaser HC261 | +2,74 | 2,43 a 3,05 | Rejeitado | Rejeitada | Não rejeitada |
Dos seis testes realizados, apenas um apresentou ausência de viés estrutural. Três comparações apresentaram simultaneamente viés estrutural e perda de precisão estrutural. Em todas as comparações a hipótese de concordância estrutural foi mantida. Entretanto, somente a frequência cardíaca medida pelo Galaxy Fit apresentou evidência compatível com equivalência metrológica completa em relação ao método de referência.