---
title: "Introdução ao acR: pipeline integrado de análise de conteúdo"
output:
  rmarkdown::html_vignette:
    toc: true
    toc_depth: 2
vignette: >
  %\VignetteIndexEntry{Introdução ao acR: pipeline integrado de análise de conteúdo}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse   = TRUE,
  comment    = "#>",
  fig.width  = 7,
  fig.height = 4,
  fig.align  = "center",
  dpi        = 120
)
```

Esta vignette percorre o pipeline completo do `acR` em um exemplo pequeno mas
realista (discursos parlamentares favoráveis e contrários a uma reforma),
mostrando o *output* efetivo de cada etapa. Se você prefere um tour de 5 minutos
com só o essencial, veja o **[Quickstart](quickstart.html)**.

```{r setup}
library(acR)
```

```{r lexico, include=FALSE}
# ac_sentiment() baixa o OpLexicon (GitHub) na primeira execução e guarda
# em cache. Sem acesso a ele, os trechos que dependem do léxico não rodam,
# em vez de interromper a vignette com erro.
tem_lexico <- tryCatch({
  suppressMessages(ac_sentiment(ac_corpus(data.frame(text = "bom"))))
  TRUE
}, error = function(e) FALSE)
```

```{r aviso-lexico, echo=FALSE, results="asis", eval=!tem_lexico}
cat(
  "> **Aviso:** o léxico OpLexicon não pôde ser baixado ao gerar esta",
  "> página (sem acesso à internet), então os trechos que dependem dele",
  "> não foram executados. Rode a vignette com internet para ver as saídas.",
  sep = "\n"
)
```

## O objeto central: `ac_corpus`

Tudo no `acR` gira em torno do `ac_corpus`, um `tibble` com colunas
padronizadas `doc_id` e `text` que carrega quaisquer metadados adicionais.
As demais funções aceitam esse objeto diretamente.

```{r corpus}
df <- data.frame(
  id      = paste0("d", 1:8),
  texto   = c(
    "Sou favoravel a reforma tributária: simplifica o sistema e reduz distorcoes.",
    "Voto contra: essa reforma vai destruir o setor produtivo brasileiro.",
    "Apoio a proposta com forte adesao, ha ganhos claros de eficiência arrecadatória.",
    "Rejeito o texto: transfere renda das familias para grandes corporacoes.",
    "Defendo a reforma que corrige as distorcoes historicas do nosso sistema.",
    "Somos contrários: o projeto beneficia apenas os mais ricos do pais.",
    "Voto sim, precisamos modernizar urgentemente a estrutura tributária.",
    "Voto não, os pequenos empresários serao os grandes prejudicados."
  ),
  partido = c("PT","PL","PT","PL","PT","PL","PT","PL"),
  posicao = c("favor","contra","favor","contra","favor","contra","favor","contra"),
  stringsAsFactors = FALSE
)

corpus <- ac_corpus(df, text = texto, docid = id, meta = c(partido, posicao))
corpus
```

## 1. Frequências e termos salientes

Antes de contar, precisamos **remover stopwords**. Sem essa etapa, os termos
mais frequentes seriam `o`, `a`, `de`, `que`: carregam pouca informação
temática e mascaram os padrões reais do corpus.

```{r contagem}
corpus_limpo <- ac_clean(corpus, remove_stopwords = "pt")

# Frequência global
freq <- ac_count(corpus_limpo)
ac_top_terms(freq, n = 8)
```

Agora quebrando por lado (`favor` vs `contra`):

```{r contagem-grupo}
freq_lado <- ac_count(corpus_limpo, by = "posicao")
ac_top_terms(freq_lado, n = 5, by = "posicao")
```

## 2. Termos distintivos com *keyness*

Quais palavras aparecem **muito mais** em um grupo do que no outro? A
métrica `chi2` (χ²) mede essa distintividade.

```{r keyness}
key <- ac_keyness(freq_lado, group = "posicao", target = "favor")
head(key, 6)
```

Visualização compacta dos termos mais distintivos:

```{r plot-keyness}
if (requireNamespace("ggplot2", quietly = TRUE)) {
  ac_plot_keyness(key, n = 6)
}
```

> **Como ler este gráfico**
>
> 1. **Onde olhar.** Cada barra é uma palavra. Barra para a **direita**
>    (verde-azulada) = mais usada nos discursos `favor`; para a
>    **esquerda** (vermelha) = mais usada nos `contra`. Quanto mais
>    comprida, maior a diferença entre os lados. Confira os números na
>    tabela `key` logo acima: `n_target` (vezes em `favor`) e
>    `n_reference` (vezes em `contra`).
>
> 2. **O que este exemplo mostra.** Do lado favorável, as três barras
>    mais longas são *distorcoes*, *sistema* e *tributária* (2 vezes em
>    `favor`, nenhuma em `contra`). Do lado contrário, a barra mais
>    longa de todo o gráfico é *grandes* (0 contra 2: "grandes
>    corporacoes", "grandes prejudicados"). As outras barras, mais
>    curtas e todas iguais, são palavras que aparecem uma vez só.
>
> 3. **Em palavras simples.** Quem defende a reforma fala do sistema
>    tributário e de corrigir distorções; quem é contra fala de quem
>    ganha e quem perde (os "grandes").
>
> 4. **Cuidado.** Com 8 discursos curtos, uma diferença de 2 contra 0 é
>    pouca evidência: leia o gráfico como pista para o que ler nos
>    textos, não como resultado estatístico (Dunning, 1993). Quando
>    várias palavras empatam (as barras curtas), o gráfico mostra as
>    primeiras em ordem alfabética: a escolha entre elas não tem
>    significado.

## 3. Sentimento por documento (OpLexicon)

Escore agregado de polaridade de cada documento, usando o léxico
OpLexicon (Souza e Vieira, 2012):

```{r sentimento, eval=tem_lexico}
sent <- ac_sentiment(corpus)
sent
```

Visualizando por documento:

```{r plot-sentimento, eval=tem_lexico}
if (requireNamespace("ggplot2", quietly = TRUE)) {
  ac_plot_sentiment(sent)
}
```

> **Como ler este gráfico**
>
> 1. **Onde olhar.** Cada barra é um discurso; o comprimento é o escore
>    (palavras positivas menos negativas do léxico OpLexicon). Para a
>    direita (verde) = positivo; para a esquerda (laranja) = negativo;
>    sem barra = zero. Compare com a posição declarada de cada discurso,
>    que você conhece pela tabela do corpus.
>
> 2. **O que este exemplo mostra.** `d3` tem o maior escore (+2: "forte"
>    e "claros"). O caso que mais ensina é `d2`, um discurso **contra**
>    ("Voto contra: essa reforma vai destruir o setor produtivo") que
>    sai **positivo**: o léxico conta "produtivo" como +1 e não tem
>    nenhuma palavra negativa para "destruir". `d6` (contra) sai zero
>    porque "ricos" conta +1 e anula "contrários" (−1).
>
> 3. **Em palavras simples.** O léxico não lê a frase, ele soma palavras
>    soltas. Quando a opinião está num verbo ("destruir") ou quando uma
>    palavra positiva aparece num contexto negativo ("setor produtivo"
>    sendo destruído), o escore erra a direção.
>
> 4. **Cuidado.** O escore é relativo ao léxico, não uma medida de "quão
>    positivo é o texto" (Taboada et al., 2011). Neste corpus, até
>    "tributária" conta como +1, um erro de domínio. Antes de usar o
>    escore, compare-o com uma amostra lida por humanos; a
>    `vignette("sentimento")` mostra esses erros em detalhe.

## 4. Escolher um modelo LLM

Antes de codificar qualitativamente, o `acR` recomenda modelos com base em
custo, idioma e tipo de tarefa. Consulta 100 % *offline*:

```{r modelos}
ac_qual_recommend_model(task = "coding", budget = "medium", lang = "pt", n = 3)
```

Base: Gilardi, Alizadeh e Kubli (2023) e Törnberg (2023).

## 5. Codificação qualitativa com LLM

Esta etapa exige chave de API (`ANTHROPIC_API_KEY`, `GROQ_API_KEY`, etc.) e
por isso não roda na construção da vignette. Estrutura mínima:

```{r coding, eval = FALSE}
codebook <- ac_qual_codebook(
  name         = "posicionamento",
  instructions = "Classifique o posicionamento sobre a reforma tributária.",
  categories   = list(
    favor  = list(
      definition   = "Manifestação favorável à reforma.",
      examples_pos = "Sou favoravel a reforma, simplifica o sistema."
    ),
    contra = list(
      definition   = "Manifestação contrária à reforma.",
      examples_pos = "Voto contra, vai destruir o setor produtivo."
    )
  )
)

codificado <- ac_qual_code(
  corpus   = corpus,
  codebook = codebook,
  model    = "anthropic/claude-sonnet-4-5"
)
```

`codificado` é um tibble com `doc_id`, `categoria`, `confidence_score`
(via *self-consistency*) e `reasoning`.

## 6. Validação humana e confiabilidade

```{r validacao-code, eval = FALSE}
# Amostra aleatória (representativa): é ela que estima a confiabilidade
# do corpus. Amostrar só os casos incertos subestimaria a concordância.
amostra <- ac_qual_sample(codificado, n = 50, strategy = "random")

# Exporta planilha para revisão humana
ac_qual_export_for_review(amostra, path = "revisao.xlsx", corpus = corpus)

# Após preencher, reimporta e calcula IRR
humano <- ac_qual_import_human("revisao.xlsx")
ac_qual_reliability(llm = codificado, human = humano)
```

Um exemplo do formato do output com dados sintéticos (equivalente ao que sai
com codificação real):

```{r validacao-demo}
llm_sim <- tibble::tibble(
  doc_id    = paste0("d", 1:8),
  categoria = c("favor","contra","favor","contra","favor","contra","favor","contra")
)
humano_sim <- tibble::tibble(
  doc_id    = paste0("d", 1:8),
  categoria = c("favor","contra","favor","contra","favor","favor","favor","contra")
  # 1 discordância em 8 casos -> ~87.5% de concordância
)

ac_qual_reliability(llm = llm_sim, human = humano_sim, bootstrap = 50)
```

As métricas incluem *percent agreement*, *alpha* de Krippendorff, AC1 de Gwet
e F1 macro, com IC via *bootstrap* e interpretação segundo Landis e Koch (1977)
e Gwet (2014).

## Próximos passos

* **[Codificação com LLMs](qualitativo-llm.html)**: codebook completo, `ellmer`,
  *self-consistency*, tradução, fusão.
* **[Análise de proposições](analise-proposicoes.html)**: pipeline real de
  ponta-a-ponta em texto legislativo brasileiro.
* **[LDA](lda.html)**: modelagem de tópicos.
* **[Sentimento](sentimento.html)**: pipeline detalhado com OpLexicon.

## Referências

DUNNING, T. Accurate methods for the statistics of surprise and
coincidence. *Computational Linguistics*, v. 19, n. 1, p. 61-74, 1993.

GILARDI, F.; ALIZADEH, M.; KUBLI, M. ChatGPT outperforms crowd workers for
text-annotation tasks. *PNAS*, v. 120, n. 30, 2023.

GWET, K. L. *Handbook of inter-rater reliability*. 4. ed. Gaithersburg:
Advanced Analytics, 2014.

KRIPPENDORFF, K. *Content analysis: an introduction to its methodology*.
4. ed. Thousand Oaks: SAGE, 2018.

LANDIS, J. R.; KOCH, G. G. The measurement of observer agreement for
categorical data. *Biometrics*, v. 33, n. 1, p. 159-174, 1977.

SOUZA, M.; VIEIRA, R. Sentiment analysis on Twitter with Portuguese language.
*STIL/SBC*, 2012.

TABOADA, M. et al. Lexicon-based methods for sentiment analysis.
*Computational Linguistics*, v. 37, n. 2, p. 267-307, 2011.

TÖRNBERG, P. ChatGPT-4 outperforms experts and crowd workers in annotating
political Twitter messages with zero-shot learning. *PLOS ONE*, v. 18, n. 4,
2023.
