Files
fn_registry/python/functions/datascience/compute_top_ngrams.md
T
egutierrez 105e56cf05 feat(eda): capítulo text_distr (TEXTO/NLP) — primer capítulo de datos no tabulares
Añade el capítulo `text_distr` al motor AutomaticEDA: perfila columnas de texto
libre largo (reseñas, descripciones, comentarios) que la distribución categórica
no resume bien. Sigue el patrón de cat_distr/num_distr (build_text_distr(profile,
ctx) -> Chapter | None) y se registra en CHAPTER_ORDER tras cat_distr.

Activación en dos fases: gate barato desde el perfil (columna no numérica con
len_mean >= 50 chars) + confirmación con muestra cruda (mediana de palabras >= 20).
Un dataset sin texto largo (p.ej. titanic) devuelve None sin tocar el informe.

Bloques por columna (Group con page_break): resumen (longitudes, vocabulario con
TTR y % hapax, idioma dominante, % duplicados, legibilidad), histograma de
longitudes, top términos (tabla + barras), bigramas/trigramas, idiomas detectados
y nube de palabras opcional. Términos ttr/hapax enganchados al glosario clicable.

Lógica delegada a 7 funciones nuevas del registry (datascience, tag eda),
estilo dict-no-throw:
- extract_text_sample (impura, push-down SQL DuckDB/Postgres)
- compute_text_length_stats, compute_vocabulary_stats, compute_top_ngrams (puras, stdlib)
- detect_corpus_language (langdetect opcional), compute_text_readability (textstat
  opcional), compute_text_duplicates (hash + datasketch opcional)

Versión barata sin modelos pesados: las piezas que dependen de una librería
opcional (langdetect, textstat, wordcloud, datasketch) degradan a omitidas sin
lanzar. Añade langdetect y textstat (ligeras) al pyproject + uv.lock.

Verificado: golden sobre dataset de reviews multi-idioma (capítulo presente en
PDF+PPTX+MD con métricas reales), titanic sin capítulo (None), degradación sin
libs, suite automatic_eda + pipeline verde (128 passed), fn index OK.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 20:38:17 +02:00

5.3 KiB

id, name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, example, tested, tests, test_file_path, file_path, params, output
id name kind lang domain version purity signature description tags uses_functions uses_types returns returns_optional error_type imports example tested tests test_file_path file_path params output
compute_top_ngrams_py_datascience compute_top_ngrams function py datascience 1.0.0 pure def compute_top_ngrams(texts, n=2, top_k=15, remove_stopwords=True) -> dict 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.
eda
datascience
text
nlp
ngrams
bigrams
trigrams
pure
python
false
re
collections
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}, ...]} true
test_bigramas
test_trigramas
test_vacio
test_stopwords
python/functions/datascience/compute_top_ngrams_test.py python/functions/datascience/compute_top_ngrams.py
name desc
texts 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 desc
n 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 desc
top_k 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 desc
remove_stopwords 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.
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

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.