Content Analysis in R: Integrated Qualitative (LLMs) and Quantitative Pipeline
Overview
Provides an integrated pipeline for content analysis combining qualitative coding assisted by large language models (LLMs) with classical quantitative text analysis. Includes modules for pre-processing (tokenization, stopwords for Brazilian Portuguese), descriptive statistics, keyness, co-occurrence networks, word clouds (including comparative and X-ray variants), sentiment analysis via OpLexicon, Latent Dirichlet Allocation (LDA), inter-coder reliability metrics (Krippendorff, Gwet), and modern visualizations based on ggplot2. Special focus on Brazilian corpora and political-institutional codebooks. Inspired by Maerz and Benoit (2025) https://quallmer.github.io/quallmer/.
Correcoes metodologicas (auditoria de codigo e interpretacoes)
Cada item abaixo e uma correcao de resultado, nao so de texto: numeros
produzidos pelas funcoes afetadas mudam em relacao a 0.5.0.
ac_tokenize(drop_punct = TRUE)(e tudo que o usa:ac_count(),ac_dictionary(),ac_wordscores(),ac_lexical_diversity(),ac_collocations(),ac_ca()): a pontuacao colada a palavra agora e removida das bordas do token ("excelente,"->"excelente"). Antes so tokens inteiramente de pontuacao eram descartados, e a mesma palavra virava dois tipos diferentes. Pontuacao interna ("e-mail","3,5") e preservada.ac_cooccurrence(): comunit = "window", cada encontro de dois termos era contado duas vezes (uma a partir de cada palavra), dobrandocooce somando 1 bit ao PMI; agora conta uma vez. Pares de um termo com ele mesmo sao ignorados. Comunit = "document", Dice e PMI passam a usar frequencia documental e numero de documentos (antes misturavam documentos com tokens, e o Dice era truncado em 1).
Show all changes in 0.6.0Hide the rest of the changes in 0.6.0
ac_collocations(n = 3): a tabela 2x2 compara a primeira palavra com o bigrama restante (antes, w1 x w3, ignorando a palavra do meio). Corrigida a afirmacao de que o log-likelihood e a medida doquanteda.textstats::textstat_collocations()(que usa lambda).ac_wordscores():rescale = "lbg"agora segue a formula de Laver, Benoit & Garry (2003, p. 316), com media e desvio-padrao dos documentos **virgens** (antes usava as referencias reestimadas); exige 2 ou mais virgens e avisa quando ha menos de 5.rescale = "mv"ancora nas referencias de menor e maior escore conhecido (Martin & Vanberg, 2008). Corrigido o ano da referencia (2008, nao 2007).ac_cluster_documents(): a distancia cosseno e calculada como distancia de corda, sqrt(2(1 - cos)), que e euclidiana e portanto valida para Ward.D2 (Murtagh & Legendre, 2014); comdistance = "cosine", o k-means roda sobre vetores normalizados. Antes o Ward recebia 1 - cos e o k-means ignorava a distancia escolhida.ac_lda_tune(): a perplexidade agora e calculada fora da amostra, por validacao cruzada (folds = 5), avaliando o teste sobre o vocabulario do treino. A perplexidade de treino, que cai quase sempre com k, continua na colunaperplexity_train.method = "Gibbs"deixou de dar erro, e...agora repassacontrolaotopicmodels::LDA().ac_lda(): aceitacontrol = list(...)(antes dava erro de argumento duplicado).ac_plot_lda_topics()mostrava rotulos como"termo___Topico 1"no eixo; agora mostra so o termo.ac_sentiment(): termos repetidos no OpLexicon (28 termos com mais de uma classe gramatical, alguns com polaridades opostas) eram contados duas vezes; agora cada termo tem uma polaridade (sinal da soma). O argumentobypassa a agregar de fato por grupo, como a documentacao dizia (antes devolvia uma linha por documento).ac_qual_irr(): o intervalo de confianca usavakappa / zcomo erro-padrao, mas ozdoirre calculado sob a hipotese nula; o IC saia de [-1, 1]. Agora e *bootstrap* percentil (novo argumentobootstrap, padrao 1000) para kappa, Fleiss e alfa.weight = "linear"estava documentado mas dava erro (oirrchama de"equal"); kappa ponderado respeita a ordem dos niveis do fator. IDs duplicados geram erro em vez de produto cartesiano silencioso.- Interpretacao das metricas de concordancia (
ac_qual_reliability(),ac_qual_irr(),ac_qual_report()): cada metrica usa a referencia propria. Alfa de Krippendorff pelas faixas de Krippendorff (2018: 0,800 / 0,667), e nao pelas de Landis & Koch; AC1 de Gwet e kappa por Landis & Koch (1977), com os limites exatos do artigo; percentual por Neuendorf (2017); F1 macro sem rotulo (nao e corrigido por acaso).confidence_leveldeac_qual_code()deixa de ser atribuido a Landis & Koch: e uma convencao do pacote. ac_qual_sample(): o padrao passa de"uncertainty"para"random". A amostra usada para estimar confiabilidade precisa ser representativa (Krippendorff, 2018, cap. 12); amostrar os casos incertos serve para diagnosticar erros, nao para estimar concordancia. Vignettes e README atualizados.ac_top_terms(): semby, uma tabela por documento (saida padrao deac_count()) era ranqueada linha a linha, sem somar o termo entre documentos; com empates mantidos, o "top 15" de um corpus pequeno devolvia o vocabulario inteiro. Agora soma por termo (ou por grupo) e devolve exatamententermos, com desempate alfabetico.ac_plot_keyness()eac_plot_tf_idf(): o mesmo problema de empates (pedirn = 6desenhava dezenas de barras); agora exatamentenpor lado ou grupo.ac_plot_top_terms()passa a mostrar o termo mais frequente no topo.ac_plot_xray(): tokenizava sem remover pontuacao, entao um termo seguido de virgula ou ponto ("trabalhadores.") nao era encontrado.ac_plot_ca(): termos com o mesmo perfil caem no mesmo ponto e os rotulos se sobrepunham ilegiveis; agora sao agrupados num rotulo so.
Correcoes de interpretacao nas vignettes
- Os 44 blocos "Como interpretar" foram reescritos como "Como ler este grafico/esta tabela", em quatro passos fixos: onde olhar, o que este exemplo mostra (com os numeros da saida), em palavras simples e cuidado (com a referencia da literatura).
vignette("quantitativo"): exemplo de analise de correspondencia trocado (no anterior, cada categoria tinha vocabulario exclusivo e o mapa era degenerado); leitura do grafico de Zipf corrigida (a linha ideal parte do primeiro ponto, que por isso sempre cai sobre ela).vignette("sentimento"): o X-ray buscava termos que nao ocorrem no corpus.vignette("lda"): o mapa de calor de gama ordena os documentos numericamente, deixando os temas visiveis em blocos.- Todas as vignettes foram re-executadas com o codigo corrigido e cada bloco "Como interpretar" foi conferido contra a saida real.
vignette("lda"): o corpus de exemplo (frases de ~7 palavras) nao permitia ao LDA recuperar os temas (pureza perto do acaso); os documentos viraram paragrafos de tres frases e o exemplo usa Gibbs com alfa = 0,1, com justificativa na literatura (Griffiths & Steyvers, 2004; Wallach, Mimno & McCallum, 2009; Hong & Davison, 2010). A escolha de K passou a usar perplexidade fora da amostra.vignette("cluster"): alturas do dendrograma e silhuetas atualizadas; incluida a leitura de Kaufman & Rousseeuw (1990) para silhueta media baixa; corrigida a comparacao com LDA (o ajuste padrao dava gama = 0,5/0,5 para todos os documentos).vignette("sentimento"): callouts reescritos a partir da saida real (erros de cobertura e de sentido no dominio do OpLexicon, Loughran & McDonald, 2011); alerta de que as densidades coloridas pelo sinal do escore separam-se por construcao.vignette("quantitativo"): keyness com ressalvas de contagem baixa e comparacoes multiplas; Wordscores comrescale = "mv"; mapa de AC lido pela direcao (Greenacre, 2007); MTLD e C de Herdan sem faixas inventadas; grafico de barras do Wordscores com alerta de eixo sem zero significativo (Cleveland, 1985).
Recursos da internet
ac_sentiment()baixa o OpLexicon do GitHub na primeira execucao. Os exemplos deac_sentiment()eac_plot_sentiment()passam a usar@examplesIf interactive(), e as vignettessentimento,introducao-acRequickstarttestam o acesso ao lexico antes: sem internet, pulam so os trechos que dependem dele e mostram um aviso, em vez de falhar. A documentacao deac_sentiment()explica o download e o cache emtools::R_user_dir("acR", "data").
Correcao de comportamento
ac_qual_codebook_translate(): exigia o pacoteellmerinstalado mesmo quando o codebook ja estava no idioma de destino (caso em que nenhuma chamada de LLM e necessaria). A checagem de idioma agora acontece antes da checagem de dependencia.
Documentacao
- Revisao ortografica completa (acentuacao) do README, das dez vignettes e dos comentarios
roxygen2emR/*.R. - Tabela "Qual metrica responde qual pergunta?" (
vignette("quantitativo")) expandida para cobrir as doze novas tecnicas introduzidas na 0.5.0, organizada em cinco familias metodologicas. - Adicionados blocos "Como interpretar" apos graficos e tabelas de resultado em todas as vignettes, explicando como ler cada visualizacao e armadilhas comuns de interpretacao.
- Adicionadas visualizacoes alternativas (como exemplos de uso de
ggplot2, sem novas funcoes exportadas) para varias das tecnicas da 0.5.0 emvignette("quantitativo")evignette("lda"). - Novas secoes "Sequencia sugerida para reportar resultados" em
vignette("quantitativo")evignette("qualitativo-llm"), com tabela de etapas e justificativa metodologica para cada uma. - Reduzido o uso de travessao (
--) para zero ocorrencias em todo o pacote (README, vignettes e comentariosroxygen2), em favor de:ou reestruturacao de frase. man/*.Rdregenerado viadevtools::document()para sincronizar com os comentariosroxygen2corrigidos.
Robustez de testes e vignettes
vignette("cluster")evignette("lda"): os trechos que dependem do pacote Suggeststopicmodelsagora sao protegidos poreval = requireNamespace("topicmodels", quietly = TRUE), evitando falha deR CMD checkem ambientes sem esse pacote instalado.- Tres testes que exercitavam caminhos de codigo dependentes de
ellmerganharamskip_if_not_installed("ellmer"), espelhando o padrao ja usado no restante da suite.
Manutencao de infraestrutura
- URLs do site do pacote unificadas em
https://ahenriquecp.com/acR/(_pkgdown.yml, README,DESCRIPTION,man/acR-package.Rd): o enderecoandersonheri.github.io/acRredireciona (301) para ele, e o CRAN aponta URLs que redirecionam. Corrigido tambem o link do repositorio da ENAP no README, cujo endereco antigo nao resolvia. - Removida do controle de versao a pasta
docs/que vinha sendo comitada por engano emmaindesde uma configuracao antiga de publicacao (hoje o site e publicado via GitHub Actions na branchgh-pages); ja estava em.Rbuildignoree agora tambem esta em.gitignore.
From NEWS.md in the release
Install
Health
- OK13 OK2026-09-08
- ERROR12 OK, 1 ERROR2026-09-07
- OK13 OK2026-08-21
- ERROR1 OK, 5 ERROR2026-08-08
Documentation
- Help pages
- 77 (3 internal)includes a package overview page
- Examples that run
- 81%60 run in a plain check (5 of them under a condition) · 5 only when donttest examples are enabled (R CMD check --as-cran) · 9 never run
- Exported functions with examples
- 100%
- Documented parameters
- 100%
- Return-value docs
- 100%
- Help pages citing references
- 34%
- Agrupamento não supervisionado de documentos
- Análise de Conteúdo Qualitativa com LLMs
- Análise de proposições legislativas HTML
- Análise de sentimento
- Análise quantitativa de texto
- Classificação com LLM Local em Escala
- Introdução ao acR: pipeline integrado de análise de conteúdo
- Modelagem de tópicos com LDA
- Quickstart: acR em 5 minutos HTML
- Replicabilidade ponta-a-ponta: do codebook ao relatório de método
Downloads
Repository
- PRs merged (all time)
- 100%
- Median days to close, 50 most recently updated closed issues
- not measured
- Median days to close, 50 most recently updated closed PRs
- 0
Stars over time
Commits over time
11 development-tooling and community-health practices detected across 5 families in the upstream repository
Checks run against github.com/andersonheri/acr on 2026-10-11.
The R CMD check workflow runs on Linux, macOS and Windows, and on R-devel
GitHub Pages site last deployed 2026-09-17 · The repository has a site deploy workflow
pkgdown site last built 2026-09-17, before release 0.6.0 (2026-10-16)
Show all practicesHide 1 practice
This repository shows signs of AI coding tools.
- Claude Codefirst seen 2026-07-16Named in .Rbuildignore: .claudePull request it wrote: opened by a project memberCommits: 12 by its own account · at least 40 crediting it in the message
- Claude Opus 4.737 commits · Jul to Aug 2026
- Claude Sonnet 53 commits · Sep 2026
Dependencies
Code & Tests
People & History
Pick two releases to compare their code metrics.
- 0.6.0Latest2026-10-16 · current release · diff ↗ ··
added 20 exports
ac_build_dictionary, ac_ca, ac_collocations, ac_dictionary, ac_dictionary_import, ac_dictionary_load, ac_dictionary_save, ac_dictionary_validate, ac_emotion, ac_kwic, ac_lexical_diversity, ac_plot_ca, ac_plot_lexical_diversity, ac_plot_readability, ac_plot_temporal, ac_plot_wordscores, ac_plot_zipf, ac_readability, ac_temporal, ac_wordscores11 hours in CRAN's queue
Listed in CRAN's incoming queue from 2026-10-15 20:47 to 2026-10-16 07:45 UTC, in 4 readings. - 0.4.0
- 0.3.42026-09-10 · diff ↗
- 0.3.3
- 0.3.22026-08-07
- RR 4.6.0 released · 2026-04-24
Package metadata
- First published
- 2026-08-07
- Total releases
- 5 / 1 yrs
- License
- MIT + file LICENSE OSI
- Minimum R
- ≥ 4.1
- Download size
- 1.5 MB
Cite
Cite this package
Run in R for the authors' entry:
citation("acR")The package provides a citation file, so citation() returns the authors' own entry.
It points to 10.21105/joss.00774.
Cite the R Observatory
For a number measured here: a download total, a coverage figure, an archival date.
From data release v2026-10-18, which the citation names so these numbers can be found later. More on citing and the projects behind them.