---
id: compute_top_ngrams_py_datascience
name: compute_top_ngrams
kind: function
lang: py
domain: datascience
version: "1.0.0"
purity: pure
signature: "def compute_top_ngrams(texts, n=2, top_k=15, remove_stopwords=True) -> dict"
description: "Calcula los n-gramas de palabras más frecuentes de un corpus de texto (n=1 unigramas, 2 bigramas, 3 trigramas...). Tokeniza a minúsculas con re.findall(r'\\w+', ...), descarta tokens numéricos y, si remove_stopwords=True, elimina stopwords ES+EN ANTES de formar los n-gramas (n-gramas contiguos sobre la secuencia de tokens de contenido, sin cruzar documentos). Pura y autocontenida con collections.Counter, sin sklearn. Estilo dict-no-throw del grupo eda: nunca lanza."
tags: [eda, datascience, text, nlp, ngrams, bigrams, trigrams, pure, python]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [re, collections]
example: |
  from datascience.compute_top_ngrams import compute_top_ngrams
  texts = ["machine learning rocks", "we love machine learning"]
  compute_top_ngrams(texts, n=2, top_k=5)
  # {"n": 2, "top": [{"ngram": "machine learning", "count": 2}, ...]}
tested: true
tests:
  - "test_bigramas"
  - "test_trigramas"
  - "test_vacio"
  - "test_stopwords"
test_file_path: "python/functions/datascience/compute_top_ngrams_test.py"
file_path: "python/functions/datascience/compute_top_ngrams.py"
params:
  - name: texts
    desc: "Lista (o tupla) de cadenas. Los elementos None o que no sean str se descartan silenciosamente. Cada documento se tokeniza por separado; los n-gramas no cruzan la frontera entre documentos."
  - name: n
    desc: "Tamaño del n-grama: 1 unigramas, 2 bigramas, 3 trigramas, etc. Valores < 1 o no enteros producen top vacío (se conserva tal cual en la clave 'n' del retorno)."
  - name: top_k
    desc: "Número máximo de n-gramas a devolver, ordenados por frecuencia descendente con desempate alfabético determinista. Default 15. Valores negativos se tratan como 0."
  - name: remove_stopwords
    desc: "Si True (default) elimina las stopwords ES+EN de una lista inline (~130 términos de altísima frecuencia) ANTES de formar los n-gramas, de modo que los n-gramas se construyen sobre la secuencia de tokens de contenido."
output: "Dict con exactamente 2 claves: n (el n recibido, sin normalizar) y top (lista de dicts {'ngram': str, 'count': int} ordenada por count descendente, longitud <= top_k). ngram es la unión de los tokens del n-grama por un espacio. Corpus vacío, tokens insuficientes para formar n-gramas o cualquier excepción interna degradan a {'n': n, 'top': []}. La función nunca lanza."
---

## Ejemplo

```python
from datascience.compute_top_ngrams import compute_top_ngrams

texts = [
    "machine learning rocks",
    "machine learning is fun",
    "we love machine learning",
]

# Bigramas (n=2): "machine learning" aparece en los 3 documentos.
compute_top_ngrams(texts, n=2, top_k=5)
# {
#   "n": 2,
#   "top": [
#       {"ngram": "machine learning", "count": 3},
#       {"ngram": "learning fun",     "count": 1},
#       {"ngram": "learning rocks",   "count": 1},
#       {"ngram": "love machine",     "count": 1},
#   ],
# }

# Unigramas con stopwords fuera (default): solo palabras de contenido.
compute_top_ngrams(["the cat sat on the mat"], n=1, top_k=3)
# {"n": 1, "top": [{"ngram": "cat", "count": 1},
#                  {"ngram": "mat", "count": 1},
#                  {"ngram": "sat", "count": 1}]}
```

## Cuando usarla

Úsala en la fase de EDA de texto cuando, además del vocabulario suelto, necesites
ver qué **combinaciones de palabras contiguas** dominan un corpus: colocaciones,
frases técnicas recurrentes ("machine learning", "data analyst"), o patrones de
trigramas en titulares/descripciones. Es el complemento natural de un perfil de
vocabulario: pasa de "qué palabras aparecen" a "qué secuencias aparecen". Llámala
con `n=1` para unigramas, `n=2` para bigramas y `n=3` para trigramas, y ajusta
`top_k` al tamaño de la tabla que vas a renderizar. Deja `remove_stopwords=True`
para que los n-gramas reflejen contenido y no conectores gramaticales.

## Gotchas

- **Las stopwords se eliminan ANTES de formar los n-gramas.** Con
  `remove_stopwords=True` la frase "data of analysis" produce el bigrama
  "data analysis" (el "of" intermedio desaparece y los tokens de contenido se
  vuelven contiguos), no "data of" ni "of analysis". Si quieres preservar la
  adyacencia literal del texto original, pasa `remove_stopwords=False`.
- **Los n-gramas NO cruzan documentos.** Cada elemento de `texts` se tokeniza y
  recorre por separado; el último token de un documento nunca se combina con el
  primero del siguiente.
- **Tokens puramente numéricos se descartan** (`tok.isdigit()`), pero los
  alfanuméricos mixtos no: "3d" o "covid19" sí cuentan como tokens. Un decimal
  como "3.5" se parte en "3" y "5" por `\w+` y ambos se descartan por numéricos.
- **La lista de stopwords es inline ES+EN**, pensada para textos generales en
  esos dos idiomas. Para otros idiomas o jerga específica de dominio puede dejar
  pasar conectores; en ese caso filtra el corpus aguas arriba o usa
  `remove_stopwords=False` y posfiltra.
- **`top` puede tener menos de `top_k` elementos** si el corpus no tiene tantos
  n-gramas distintos. El desempate por frecuencia es alfabético (determinista),
  no por orden de aparición.
