A dupla com maior altura média venceu 55,0% das 59.216 partidas comparáveis. A taxa foi maior quando a diferença de altura aumentou. Já a frequência de terceiro set mudou pouco entre as faixas observadas.
A altura é uma característica fácil de observar na formação de duplas, mas ela diz pouco sozinha sobre o que acontece em quadra. Este trabalho investiga duas perguntas: a dupla mais alta vence com mais frequência? E jogos entre duplas de alturas parecidas chegam mais ao terceiro set? As respostas ajudam técnicos, atletas e analistas a avaliar o peso que vale a pena dar à altura ao descrever um confronto.
Comparamos adversários da mesma partida nos circuitos AVP e FIVB. Medimos a altura da dupla pela média dos dois atletas, calculamos a diferença entre duplas e comparamos a proporção de vitórias com a referência de 50%. Separamos os resultados por faixa de diferença, circuito e categoria. Para a segunda pergunta, usamos a presença de terceiro set como um indicador simples de equilíbrio. A investigação é descritiva: ela mede associações observadas no arquivo.
Todos os pacotes são carregados na configuração inicial.
instalar_pacotes.R instala apenas os que estiverem
faltando. A tabela indica a função de cada dependência usada pelo
relatório.
| Pacote | Uso no projeto |
|---|---|
readr |
Importação do CSV, interpretação de datas e números e exportação. |
dplyr |
Seleção, filtros, variáveis, junções e resumos por grupo. |
tidyr |
Separação dos sets e mudança entre dados largos e longos. |
stringr |
Normalização de texto e interpretação de duração e placar. |
ggplot2 |
Gráficos estáticos com escalas e rótulos definidos. |
scales |
Formatação percentual dos eixos. |
DT |
Tabela interativa de recortes com busca, ordenação e filtros. |
knitr |
Execução dos blocos de código e produção das tabelas do relatório. |
rmarkdown |
Geração do HTML autocontido usado no RPubs. |
library(rmarkdown)
library(knitr)
library(readr)
library(dplyr)
library(tidyr)
library(stringr)
library(ggplot2)
library(scales)
library(DT)
O BigTimeStats
reuniu resultados e estatísticas de torneios de vôlei de praia dos
circuitos AVP e FIVB. Na publicação
que apresentou o conjunto em 2017, o responsável descreve o uso do
acervo para explorar desempenho de atletas e parcerias. Usamos o full_archive.csv
da versão de 29/09/2022, recuperado em 07/11/2026. A data de
compilação da versão é distinta das datas esportivas. Os eventos
registrados vão de 16/09/2000 a 23/09/2022. A fonte não
fornece a data exata de coleta de cada linha.
A origem contém 85.509 registros por partida e 65
colunas. Os campos incluem texto, datas, contagens, medidas
físicas e resultados. As colunas w_ descrevem a dupla
vencedora; as colunas l_, a perdedora. date
indica a data do torneio, em geral o início, e
country o país do torneio. As alturas estão em polegadas e
os minutos precisam ser obtidos de uma duração no formato horas:minutos.
Os campos de desempenho não têm a mesma cobertura em todos os circuitos
e torneios.
Dados de BigTimeStats, sob CC BY-NC-SA 4.0. Os dados tratados mantêm essa licença; as transformações estão descritas neste relatório.
Lemos o arquivo em Latin-1, como indicado pela fonte, e fixamos sua
versão para que a análise possa ser repetida. O CSV entra como texto;
depois convertemos as datas para Date, as medidas e
contagens usadas para número e as categorias para fatores. Tratamos
vazios e marcadores de ausência como NA. Não houve
duplicatas exatas na importação (0). A combinação de campos de torneio e
número de partida da fonte tem 20.514 registros excedentes em
chaves repetidas; preservamos as linhas e atribuímos um
identificador sequencial próprio para evitar junções indevidas. A base
não permite provar que toda ocorrência semelhante seja um jogo
distinto.
versao_base <- "0fa423c5704de46a8cf0d9b8b542c694c0ae2276"
url_base <- paste0(
"https://raw.githubusercontent.com/BigTimeStats/beach-volleyball/",
versao_base, "/data/full_archive/full_archive.csv"
)
arquivo_base <- file.path("dados", "full_archive.csv")
md5_esperado <- "7a89bbe38e9a03ffb8b40bca8c64988d"
# A cópia incluída permite recompilar sem internet. Caso falte, baixa a mesma versão.
if (!file.exists(arquivo_base)) {
dir.create(dirname(arquivo_base), recursive = TRUE, showWarnings = FALSE)
utils::download.file(url_base, arquivo_base, mode = "wb", quiet = TRUE)
}
if (!identical(unname(tools::md5sum(arquivo_base)), md5_esperado)) {
stop("O CSV difere da versão analisada. Use o arquivo original do projeto.")
}
# Ler como texto dá controle sobre o tipo e os valores ausentes de cada campo.
base_bruta <- readr::read_csv(
arquivo_base,
locale = readr::locale(encoding = "ISO-8859-1", decimal_mark = "."),
col_types = readr::cols(.default = readr::col_character()),
na = c("", "NA", "N/A"), trim_ws = FALSE, progress = FALSE
)
stopifnot(nrow(readr::problems(base_bruta)) == 0L)
base_unica <- distinct(base_bruta)
n_duplicadas <- nrow(base_bruta) - nrow(base_unica)
normalizar_texto <- function(x) na_if(str_squish(x), "")
minutos <- function(x) {
partes <- str_match(x, "^([0-9]+):([0-5][0-9])$")
total <- as.integer(partes[, 2]) * 60L + as.integer(partes[, 3])
na_if(total, 0L)
}
# Mantém o número fornecido pela fonte e cria uma chave própria para as junções.
partidas <- base_unica |>
transmute(
id_partida = row_number(),
circuito = factor(normalizar_texto(circuit), levels = c("AVP", "FIVB")),
categoria = factor(normalizar_texto(gender), levels = c("W", "M"),
labels = c("Feminino", "Masculino")),
torneio = normalizar_texto(tournament),
pais_evento = normalizar_texto(country),
data_evento = readr::parse_date(date, format = "%Y-%m-%d"),
ano = readr::parse_integer(year),
periodo = cut(ano, breaks = c(1999, 2007, 2014, 2022),
labels = c("2000–2007", "2008–2014", "2015–2022")),
numero_fonte = normalizar_texto(match_num),
fase = normalizar_texto(round),
placar = normalizar_texto(score),
duracao_min = minutos(normalizar_texto(duration)),
w_atleta_1 = normalizar_texto(w_player1),
w_atleta_2 = normalizar_texto(w_player2),
l_atleta_1 = normalizar_texto(l_player1),
l_atleta_2 = normalizar_texto(l_player2),
w_altura_1_pol = readr::parse_double(w_p1_hgt),
w_altura_2_pol = readr::parse_double(w_p2_hgt),
l_altura_1_pol = readr::parse_double(l_p1_hgt),
l_altura_2_pol = readr::parse_double(l_p2_hgt)
)
stopifnot(
!anyNA(partidas$circuito), !anyNA(partidas$categoria),
!anyNA(partidas$data_evento), !anyNA(partidas$periodo),
all(format(partidas$data_evento, "%Y") == partidas$ano)
)
# O contador da fonte se repete inclusive dentro de torneio, data e categoria.
chaves_fonte <- partidas |>
distinct(circuito, categoria, torneio, pais_evento, data_evento, numero_fonte)
n_repeticoes_chave <- nrow(partidas) - nrow(chaves_fonte)
campos_auditoria <- c("score", "duration", "w_p1_hgt", "w_p2_hgt",
"l_p1_hgt", "l_p2_hgt", "w_p1_tot_attacks")
ausencias <- vapply(base_bruta[campos_auditoria], function(x) sum(is.na(x)), integer(1))
n_duracao_invalida <- sum(is.na(partidas$duracao_min)) - sum(is.na(base_unica$duration))
| Campo | Ausências no CSV | Parcela dos registros |
|---|---|---|
| Placar | 24 | 0,0% |
| Duração | 2.752 | 3,2% |
| Altura 1, vencedora | 6.036 | 7,1% |
| Altura 2, vencedora | 6.073 | 7,1% |
| Altura 1, perdedora | 9.435 | 11,0% |
| Altura 2, perdedora | 9.439 | 11,0% |
| Ataques do atleta 1, vencedora | 69.992 | 81,9% |
Mantivemos ausências de altura sem imputação. Uma média calculada com só um atleta confundiria a altura individual com a da dupla. As estatísticas detalhadas ficaram fora do recorte principal: por exemplo, a contagem de ataques do primeiro atleta vencedor falta em 81,9% dos registros. Durações vazias seguem ausentes. O tratamento marcou outros 0 valores como ausentes por duração zero ou formato inválido. As ausências desse campo só afetam a comparação de duração.
O texto 21-16, 17-21, 15-10 vira três linhas, uma para
cada set. Em cada linha, extraímos os pontos das duas duplas. Para
aceitar um placar, exigimos dois ou três pares numéricos sem set
empatado, com duas vitórias em sets para a dupla indicada como
vencedora, inclusive no último set. Isso seleciona registros compatíveis
com uma disputa melhor de três. O filtro exclui anotações de
desistência, placares ausentes e formatos incompatíveis; ele não
certifica todas as regras de pontuação de cada torneio histórico.
# Só interpreta textos com dois ou três pares de pontos separados por vírgulas.
padrao_set <- "[0-9]+\\s*-\\s*[0-9]+"
padrao_jogo <- paste0("^", padrao_set, "(?:\\s*,\\s*", padrao_set, "){1,2}$")
sets <- partidas |>
select(id_partida, placar) |>
filter(str_detect(placar, padrao_jogo)) |>
tidyr::separate_longer_delim(placar, delim = ",") |>
group_by(id_partida) |>
mutate(set = row_number()) |>
ungroup() |>
tidyr::extract(
placar, c("pontos_vencedora", "pontos_perdedora"),
regex = "^\\s*([0-9]+)\\s*-\\s*([0-9]+)\\s*$", convert = TRUE
)
placares <- sets |>
group_by(id_partida) |>
summarise(
n_sets_lidos = n(),
sets_da_vencedora = sum(pontos_vencedora > pontos_perdedora),
sem_empate = all(pontos_vencedora != pontos_perdedora),
venceu_ultimo = last(pontos_vencedora > pontos_perdedora),
.groups = "drop"
)
| Classificação do placar | Registros |
|---|---|
| Compatível | 84.116 |
| Outro formato | 1.356 |
| Ausente | 24 |
| Inconsistente | 13 |
O arquivo original tem uma linha por partida, com os dois lados em
colunas diferentes. O pivot_longer() reorganiza esses
campos em duas linhas por partida e nos permite aplicar a mesma
conversão para os dois lados. Cada polegada equivale a 2,54
cm. Calculamos a média dos dois atletas e voltamos a uma linha
por partida com pivot_wider(). As tabelas de alturas e
resumo dos sets são unidas pelo identificador criado. Conferimos que as
junções preservaram a quantidade de registros.
# w_ e l_ identificam as duas duplas. Uma linha por dupla permite a mesma
# transformação para os dois lados, sem usar o nome de atleta como identificador.
duplas <- partidas |>
select(id_partida, matches("^[wl]_")) |>
tidyr::pivot_longer(
-id_partida, names_to = c("lado", ".value"), names_pattern = "^([wl])_(.+)$"
) |>
mutate(
resultado = if_else(lado == "w", "Vitória", "Derrota"),
altura_1_cm = altura_1_pol * 2.54,
altura_2_cm = altura_2_pol * 2.54,
media_pol = (altura_1_pol + altura_2_pol) / 2,
maior_pol = pmax(altura_1_pol, altura_2_pol)
)
# Voltamos ao nível da partida para comparar os adversários na mesma observação.
alturas_partida <- duplas |>
select(id_partida, lado, media_pol, maior_pol) |>
tidyr::pivot_wider(names_from = lado, values_from = c(media_pol, maior_pol))
faixas <- c("0 cm", "Até 2,54 cm", ">2,54 a 5,08 cm", ">5,08 cm")
partidas_tratadas <- partidas |>
select(-matches("^[wl]_")) |>
left_join(placares, by = "id_partida", relationship = "one-to-one") |>
left_join(alturas_partida, by = "id_partida", relationship = "one-to-one") |>
mutate(
status_placar = case_when(
is.na(placar) ~ "Ausente",
is.na(n_sets_lidos) ~ "Outro formato",
!sem_empate | sets_da_vencedora != 2L | !venceu_ultimo ~ "Inconsistente",
TRUE ~ "Compatível"
),
n_sets = if_else(status_placar == "Compatível", n_sets_lidos, NA_integer_),
terceiro_set = n_sets == 3L,
altura_vencedora_cm = media_pol_w * 2.54,
altura_perdedora_cm = media_pol_l * 2.54,
altura_completa = !is.na(media_pol_w) & !is.na(media_pol_l),
diferenca_pol = media_pol_w - media_pol_l,
diferenca_cm = abs(diferenca_pol) * 2.54,
faixa_diferenca = cut(abs(diferenca_pol), c(-Inf, 0, 1, 2, Inf), labels = faixas),
mais_alta_venceu = if_else(diferenca_pol == 0, NA, diferenca_pol > 0),
diferenca_maior_atleta_pol = maior_pol_w - maior_pol_l
) |>
select(-n_sets_lidos, -sets_da_vencedora, -sem_empate, -venceu_ultimo,
-media_pol_w, -media_pol_l, -maior_pol_w, -maior_pol_l, -diferenca_pol)
amostra <- filter(partidas_tratadas, status_placar == "Compatível", altura_completa)
amostra_vitorias <- filter(amostra, !is.na(mais_alta_venceu))
stopifnot(
nrow(duplas) == 2L * nrow(partidas),
nrow(partidas_tratadas) == nrow(partidas), !anyDuplicated(partidas_tratadas$id_partida),
nrow(amostra) >= 5000L, ncol(amostra) >= 10L,
all(amostra$n_sets %in% c(2L, 3L)),
all(amostra$diferenca_cm >= 0),
all(!is.na(amostra_vitorias$mais_alta_venceu))
)
Dos 85.509 registros de origem, 84.116 passaram pelo filtro de placar e 65.357 partidas, com 22 colunas, tinham também as quatro alturas. Destas, 6.141 tinham médias iguais. Elas entram na análise do terceiro set; a taxa de vitória da dupla mais alta usa as 59.216 partidas restantes.
| Circuito | Categoria | Original | Placar compatível | Na amostra | Cobertura |
|---|---|---|---|---|---|
| AVP | Feminino | 12.263 | 12.104 | 9.029 | 73,6% |
| AVP | Masculino | 15.109 | 14.834 | 9.646 | 63,8% |
| FIVB | Feminino | 28.337 | 27.948 | 22.894 | 80,8% |
| FIVB | Masculino | 29.800 | 29.230 | 23.788 | 79,8% |
A cobertura por grupo vai de 63,8% a 80,8%. A comparação deve ser lida como um retrato das partidas com medidas disponíveis, pois os jogos excluídos podem ter perfis diferentes.
| ID | Circuito | Categoria | Ano | Placar | Vencedora (cm) | Perdedora (cm) | Diferença (cm) | Sets |
|---|---|---|---|---|---|---|---|---|
| 1 | AVP | Masculino | 2002 | 21-18, 21-12 | 195,58 | 198,12 | 2,54 | 2 |
| 2 | AVP | Masculino | 2002 | 21-16, 17-21, 15-10 | 194,31 | 194,31 | 0,00 | 3 |
| 3 | AVP | Masculino | 2002 | 21-18, 21-18 | 194,31 | 194,31 | 0,00 | 2 |
| 4 | AVP | Masculino | 2002 | 21-16, 21-15 | 193,04 | 198,12 | 5,08 | 2 |
| 5 | AVP | Masculino | 2002 | 20-22, 23-21, 15-10 | 196,85 | 187,96 | 8,89 | 3 |
| 7 | AVP | Masculino | 2002 | 21-15, 22-20 | 198,12 | 198,12 | 0,00 | 2 |
| Variável de interesse | Significado | Resumo na amostra |
|---|---|---|
circuito, categoria |
AVP ou FIVB; feminino ou masculino. | Quatro grupos com cobertura na Tabela 3. |
altura_vencedora_cm |
Altura média dos dois atletas vencedores, em cm. | Mediana de 188,0 cm. |
altura_perdedora_cm |
Altura média dos dois atletas perdedores, em cm. | Mediana de 186,7 cm. |
diferenca_cm |
Diferença absoluta entre as médias das duplas. | Mediana de 3,81 cm. |
mais_alta_venceu |
Verdadeiro se venceu a dupla com maior média. | NA quando as médias são iguais. |
n_sets, terceiro_set |
Número de sets do placar; indicador de três sets. | 33,5% da amostra chegou a três sets. |
duracao_min |
Duração em minutos, quando disponível. | Mediana de 42 min; 504 ausências. |
Para cada partida com médias diferentes, contamos uma vitória da dupla mais alta se a altura média da vencedora for superior à da perdedora. A taxa usa o número de partidas, e não o de atletas ou sets. Organizamos a diferença absoluta em faixas de uma e duas polegadas convertidas para centímetros. A referência de 50% representa uma divisão igual de vitórias entre duplas mais altas e mais baixas.
cobertura <- partidas_tratadas |>
group_by(circuito, categoria) |>
summarise(
registros = n(),
placar_compativel = sum(status_placar == "Compatível"),
analisadas = sum(status_placar == "Compatível" & altura_completa),
proporcao = analisadas / registros,
.groups = "drop"
)
por_faixa <- amostra_vitorias |>
group_by(faixa_diferenca) |>
summarise(jogos = n(), vitorias = sum(mais_alta_venceu), taxa = vitorias / jogos,
.groups = "drop")
por_grupo <- amostra_vitorias |>
group_by(circuito, categoria) |>
summarise(jogos = n(), vitorias = sum(mais_alta_venceu), taxa = vitorias / jogos,
.groups = "drop")
por_recorte <- amostra_vitorias |>
group_by(circuito, categoria, periodo, faixa_diferenca) |>
summarise(jogos = n(), vitorias = sum(mais_alta_venceu), taxa = vitorias / jogos,
.groups = "drop")
equilibrio <- amostra |>
group_by(faixa_diferenca) |>
summarise(jogos = n(), com_terceiro = sum(terceiro_set), taxa = com_terceiro / jogos,
.groups = "drop")
duracao <- amostra |>
filter(!is.na(duracao_min)) |>
group_by(n_sets) |>
summarise(jogos = n(), mediana = median(duracao_min),
q1 = as.numeric(quantile(duracao_min, 0.25)),
q3 = as.numeric(quantile(duracao_min, 0.75)), .groups = "drop")
maior_atleta <- amostra |>
filter(diferenca_maior_atleta_pol != 0) |>
summarise(jogos = n(), taxa = mean(diferenca_maior_atleta_pol > 0))
n_placar <- sum(partidas_tratadas$status_placar == "Compatível")
n_empates_altura <- nrow(amostra) - nrow(amostra_vitorias)
taxa_geral <- mean(amostra_vitorias$mais_alta_venceu)
ggplot(por_faixa, aes(faixa_diferenca, taxa, group = 1)) +
geom_hline(yintercept = 0.5, linetype = "dashed", color = "#647785") +
geom_line(color = verde, linewidth = 0.9) +
geom_point(color = verde, size = 4) +
geom_text(aes(label = pct(taxa)), nudge_y = 0.012, color = verde,
fontface = "bold", size = 4.5) +
scale_y_continuous(labels = rotulo_pct, breaks = seq(0.45, 0.65, by = 0.05),
limits = c(0.45, 0.65)) +
labs(title = "A dupla mais alta venceu mais com diferenças maiores",
subtitle = "Somente jogos com alturas médias diferentes; tracejado em 50%",
x = "Diferença entre as alturas médias das duplas",
y = "Vitórias da dupla mais alta",
caption = "Fonte: BigTimeStats. Cada partida tem o mesmo peso.") +
tema_volei
| Faixa | Partidas | Vitórias da mais alta | Taxa |
|---|---|---|---|
| Até 2,54 cm | 23.069 | 12.068 | 52,3% |
| >2,54 a 5,08 cm | 17.097 | 9.275 | 54,2% |
| >5,08 cm | 19.050 | 11.227 | 58,9% |
A taxa foi de 52,3% na menor faixa e 58,9% quando a diferença passou de 5,08 cm. A distância entre as duas taxas foi de 6,6 p.p.. Mesmo na maior faixa, a dupla mais baixa venceu 41,1% das vezes. Portanto, a altura média é uma descrição útil, mas há bastante variação nos resultados.
| Circuito | Categoria | Partidas | Vitórias da mais alta | Taxa |
|---|---|---|---|---|
| AVP | Feminino | 8.277 | 4.544 | 54,9% |
| AVP | Masculino | 8.635 | 5.114 | 59,2% |
| FIVB | Feminino | 20.681 | 11.216 | 54,2% |
| FIVB | Masculino | 21.623 | 11.696 | 54,1% |
O grupo com a maior taxa observada foi AVP masculino, com 59,2%. A taxa variou entre os quatro grupos. A diferença pode refletir perfis dos torneios, critérios de entrada e cobertura das alturas, além de características de jogo. A tabela interativa permite verificar quantos jogos sustentam cada comparação por período e faixa. Recortes pequenos tendem a oscilar mais.
recortes <- por_recorte |>
select(Circuito = circuito, Categoria = categoria, `Período` = periodo,
`Diferença de altura` = faixa_diferenca, Partidas = jogos,
`Vitórias` = vitorias, `Taxa de vitória` = taxa)
# Seletores por coluna usando a própria API da tabela no navegador.
filtros <- DT::JS(
"function () {",
" var api = this.api(), area = document.createElement('div');",
" area.className = 'filtros-recortes';",
" var painel = api.table().container();",
" painel.insertBefore(area, painel.firstChild);",
" api.columns([0, 1, 2, 3]).every(function () {",
" var coluna = this, rotulo = document.createElement('label');",
" var seletor = document.createElement('select');",
" rotulo.textContent = coluna.header().textContent.trim();",
" seletor.add(new Option('Todos', ''));",
" coluna.data().unique().sort().each(function (v) { seletor.add(new Option(v, v)); });",
" seletor.addEventListener('change', function () {",
" var termo = $.fn.dataTable.util.escapeRegex(seletor.value);",
" coluna.search(termo ? '^' + termo + '$' : '', true, false).draw();",
" });",
" rotulo.appendChild(seletor); area.appendChild(rotulo);",
" });",
"}"
)
DT::datatable(
recortes, rownames = FALSE, class = "stripe compact",
caption = "Tabela 7. Selecione os filtros para explorar os recortes de vitória.",
options = list(
pageLength = 8, lengthMenu = c(8, 16, 36), scrollX = TRUE, initComplete = filtros,
language = list(search = "Buscar:", lengthMenu = "Mostrar _MENU_ recortes",
info = "_START_ a _END_ de _TOTAL_ recortes",
infoEmpty = "Nenhum recorte", zeroRecords = "Nenhum resultado",
paginate = list(previous = "Anterior", `next` = "Próxima"))
)
) |>
DT::formatPercentage("Taxa de vitória", digits = 1, dec.mark = ",", mark = ".")
Tabela 7. Filtros por circuito, categoria, período e diferença de altura.
Como verificação, substituímos a média pela altura do atleta mais alto de cada dupla. Entre as 55.494 partidas em que essa outra medida distingue as duplas, a dupla com o atleta mais alto venceu 55,9%. A direção da associação se mantém. O denominador muda porque a definição de empate de altura é outra.
Terceiro set indica que cada lado venceu um dos dois primeiros sets. Usamos esse indicador para perguntar se confrontos com alturas mais próximas vão mais vezes ao set decisivo. Aqui, mantemos a faixa de 0 cm, porque empates de altura ainda são informativos para essa pergunta.
ggplot(equilibrio, aes(faixa_diferenca, taxa)) +
geom_col(fill = azul, width = 0.62) +
geom_text(aes(label = pct(taxa)), vjust = -0.55, color = azul,
fontface = "bold", size = 4.2) +
scale_y_continuous(labels = rotulo_pct, limits = c(0, 0.42),
breaks = seq(0, 0.4, by = 0.1), expand = c(0, 0)) +
labs(title = "A frequência de terceiro set mudou pouco entre as faixas",
subtitle = "Partidas com placar compatível e as quatro alturas conhecidas",
x = "Diferença entre as alturas médias das duplas",
y = "Partidas com terceiro set",
caption = "Fonte: BigTimeStats. Empates de altura entram na primeira barra.") +
tema_volei
As taxas ficaram entre 32,6% e 33,9%, uma amplitude de 1,2 p.p.. Embora a diferença de altura separe melhor as taxas de vitória, ela distingue pouco os jogos que chegam ao terceiro set nesse recorte. Esse indicador não mede a diferença de pontos dentro de um set.
ggplot(duracao, aes(mediana, factor(n_sets))) +
geom_segment(aes(x = q1, xend = q3, yend = factor(n_sets)),
color = "#a7cac7", linewidth = 4, lineend = "round") +
geom_point(color = verde, size = 4) +
geom_text(aes(label = paste0(num(mediana), " min")), nudge_y = 0.17,
color = verde, fontface = "bold", size = 4.3) +
scale_x_continuous(breaks = seq(20, 70, 10), limits = c(20, 70)) +
labs(title = "Os jogos com terceiro set duraram mais",
subtitle = "Ponto: mediana. Segmento: metade central das durações.",
x = "Duração (minutos)", y = "Número de sets",
caption = "Fonte: BigTimeStats. Apenas partidas com duração registrada e positiva.") +
tema_volei + theme(panel.grid.major.x = element_line(color = "#e3e9ec"),
panel.grid.major.y = element_blank())
Entre as partidas com duração disponível, a mediana passou de 38 para 54 minutos. Os denominadores foram 43.187 jogos de dois sets e 21.666 de três. A mediana descreve melhor o tempo típico quando alguns jogos são muito longos. Para organizar horários, a diferença observada é um ponto de partida; o tempo real depende do confronto.
A dupla com maior altura média venceu um pouco mais da metade das partidas em que a comparação era possível. A proporção passou de 52,3% para 58,9% entre as faixas extremas, e a associação variou por circuito e categoria. Em contraste, cerca de um terço dos jogos chegou ao terceiro set em todas as faixas. Assim, a altura média ajuda a descrever uma vantagem observada no resultado, mas oferece pouco para distinguir os confrontos que terão set decisivo.
O resultado vem da comparação de adversários do mesmo jogo, após converter alturas, interpretar placares e unir as tabelas por partida. Para técnicos e atletas, a medida pode compor uma avaliação junto com a técnica de saque, recepção e ataque. Para quem organiza torneios, a duração típica por número de sets informa o planejamento, com margem para a variabilidade.
As partidas com dados completos podem não representar todo o acervo. Os mesmos atletas e duplas aparecem em muitos jogos, e a análise dá o mesmo peso a cada partida. Não controlamos nível técnico, cabeça de chave, experiência, fase ou alterações históricas nas competições. Por isso, os percentuais são descritivos e não estimam um efeito causal da altura. Em uma extensão, seria útil vincular um identificador estável de atletas, controlar diferenças de nível e fase e testar a estabilidade do padrão por torneio e temporada. Estatísticas de ataque e bloqueio poderiam ajudar nessa investigação onde a cobertura fosse suficiente.
O código de importação, tratamento, resumos e gráficos está disponível nos blocos Code. Os resultados são calculados na geração deste HTML. A tabela analítica pode ser regenerada a partir do CSV original fixado por versão.
readr::write_csv(amostra, file.path("dados", "partidas_analisadas.csv"), na = "")
full_archive.csv,
versão analisada. Recuperado em 07/11/2026.sessionInfo()
## R version 4.5.0 (2025-04-11)
## Platform: x86_64-pc-linux-gnu
## Running under: Debian GNU/Linux 13 (trixie)
##
## Matrix products: default
## BLAS: /tmp/volei-r-local/usr/lib/x86_64-linux-gnu/blas/libblas.so.3.12.1
## LAPACK: /tmp/volei-r-local/usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.12.1; LAPACK version 3.12.0
##
## locale:
## [1] LC_CTYPE=C.UTF-8 LC_NUMERIC=C LC_TIME=C.UTF-8
## [4] LC_COLLATE=C.UTF-8 LC_MONETARY=C.UTF-8 LC_MESSAGES=C.UTF-8
## [7] LC_PAPER=C.UTF-8 LC_NAME=C LC_ADDRESS=C
## [10] LC_TELEPHONE=C LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C
##
## time zone: America/Recife
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] DT_0.33 scales_1.3.0 ggplot2_3.5.1 stringr_1.5.1 tidyr_1.3.1
## [6] dplyr_1.1.4 readr_2.1.5 knitr_1.50 rmarkdown_2.29
##
## loaded via a namespace (and not attached):
## [1] bit_4.6.0 gtable_0.3.6 jsonlite_1.9.1 crayon_1.5.3
## [5] compiler_4.5.0 tidyselect_1.2.1 parallel_4.5.0 jquerylib_0.1.4
## [9] yaml_2.3.10 fastmap_1.2.0 R6_2.6.1 generics_0.1.3
## [13] htmlwidgets_1.6.4 tibble_3.2.1 munsell_0.5.1 bslib_0.9.0
## [17] pillar_1.10.1 tzdb_0.5.0 rlang_1.1.5 cachem_1.1.0
## [21] stringi_1.8.4 xfun_0.51 sass_0.4.9 bit64_4.6.0-1
## [25] cli_3.6.4 withr_3.0.2 magrittr_2.0.3 crosstalk_1.2.1
## [29] digest_0.6.37 grid_4.5.0 vroom_1.6.5 hms_1.1.3
## [33] lifecycle_1.0.4 vctrs_0.6.5 evaluate_1.0.3 glue_1.8.0
## [37] farver_2.1.2 colorspace_2.1-1 purrr_1.0.4 tools_4.5.0
## [41] pkgconfig_2.0.3 htmltools_0.5.8.1