--- id: missingness_rank_bar_figure_py_datascience name: missingness_rank_bar_figure kind: function lang: py domain: datascience version: "1.0.0" purity: impure signature: "def missingness_rank_bar_figure(names, pcts, title=\"% de valores faltantes por columna\") -> \"matplotlib.figure.Figure\"" description: "Construye una figura matplotlib de barras horizontales que ordena las columnas de un dataset por su porcentaje de valores faltantes (0-100), la mayor arriba, etiquetando cada barra con su NN.N% al final. Usa ax.barh, eje X fijo 0-100 y labels truncados a ~22 chars. Devuelve un matplotlib.figure.Figure listo para rasterizar por el renderer del informe EDA (capítulo de datos faltantes). Backend Agg sin pyplot global; defensivo ante listas vacías, longitudes desiguales o valores no numéricos (nunca lanza)." tags: [eda, missing, missingness, ranking, bar, barh, matplotlib, figure, visualization, datascience, impure] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: [matplotlib] example: | from datascience.missingness_rank_bar_figure import missingness_rank_bar_figure names = ["edad", "ingresos", "ciudad", "email"] pcts = [12.5, 40.0, 3.2, 0.0] fig = missingness_rank_bar_figure(names, pcts, title="% de valores faltantes por columna") tested: true tests: - "test_returns_figure_with_axes" - "test_sorted_descending_largest_on_top" - "test_empty_lists_do_not_raise_and_returns_figure" - "test_xlim_is_zero_to_hundred" - "test_length_mismatch_and_non_numeric_are_handled" test_file_path: "python/functions/datascience/missingness_rank_bar_figure_test.py" file_path: "python/functions/datascience/missingness_rank_bar_figure.py" params: - name: names desc: "Lista de nombres de columna. Puede venir vacía (devuelve figura \"sin datos faltantes\"). Los items se convierten a str y se truncan a ~22 chars con elipsis para las etiquetas del eje Y; los originales no se mutan." - name: pcts desc: "Lista paralela a names con el % de nulos en [0,100]. Valores None, NaN o no numéricos se coercen a 0.0 y los negativos se recortan a 0. Si len(names) != len(pcts) se recorta al menor de ambos para no romper." - name: title desc: "Título de la figura. Se trunca a ~60 chars con elipsis si es muy largo. Default \"% de valores faltantes por columna\"." output: "Un matplotlib.figure.Figure (figsize 6.4 x alto adaptativo según nº de barras, dpi 150) con un Axes de barras horizontales (ax.barh) ordenadas por % descendente, la mayor arriba. Eje X fijado a [0,100] con label \"% faltante\", etiquetas del eje Y truncadas a ~22 chars, y cada barra anotada con su NN.N% al final. Si names o pcts vienen vacíos devuelve una Figure con texto centrado \"sin datos faltantes\"; cualquier error inesperado se captura y devuelve una Figure con el mensaje de error (nunca lanza). El caller rasteriza/cierra la figura; la función no la muestra ni la guarda." --- ## Ejemplo ```python from datascience.missingness_rank_bar_figure import missingness_rank_bar_figure # % de nulos por columna (p. ej. (df.isnull().mean() * 100). names = ["edad", "ingresos", "ciudad", "email"] pcts = [12.5, 40.0, 3.2, 0.0] fig = missingness_rank_bar_figure( names, pcts, title="% de valores faltantes por columna", ) # ingresos (40.0%) queda arriba; email (0.0%) abajo. # El renderer del informe lo rasteriza; aquí solo persistimos para inspección. fig.savefig("/tmp/missingness_rank.png") ``` ## Cuando usarla Úsala al abrir el capítulo de datos faltantes de un informe EDA para responder "¿qué columnas están más incompletas?" de un vistazo. Pásale los nombres de columna y el % de nulos de cada una (`(df.isnull().mean() * 100).round(1)`); la función se encarga de ordenar de mayor a menor y poner la peor arriba. Es la pareja "magnitud" del heatmap de co-ocurrencia: las barras dicen *cuánto* falta en cada columna, el heatmap dice *si esas ausencias están relacionadas* entre columnas. ## Gotchas - **Impura por matplotlib.** Toca la maquinaria de render. Usa el backend `Agg` y la API orientada a objetos `Figure`/`add_subplot` — NUNCA `pyplot.*` aquí, para no tocar el estado global ni filtrar figuras entre llamadas. `pyplot` NO es thread-safe; esta función evita ese riesgo construyendo el `Figure` directamente, así que es segura de llamar en bucle desde el renderer. - **El caller cierra la figura.** Devuelve el `Figure` pero no lo muestra ni lo guarda. Quien la consume debe rasterizarla y luego liberarla (`matplotlib.pyplot.close(fig)`) para no acumular memoria en lotes grandes. - **Espera porcentajes 0-100, no fracciones 0-1.** El eje X está fijado a `[0, 100]`. Si pasas fracciones (`0.4` en vez de `40.0`) las barras saldrán pegadas al origen. Multiplica por 100 antes de llamar. - **Alto adaptativo.** La altura de la figura crece con el número de barras (hasta un tope) para que reports con muchas columnas sigan legibles; aun así, conviene filtrar a las columnas con algún nulo antes de llamar para no listar decenas de barras a 0%. - **Defensiva, nunca lanza.** Listas vacías, longitudes desiguales, valores `None`/`NaN`/no numéricos o cualquier error inesperado se manejan sin propagar: en el peor caso devuelve una `Figure` con "sin datos faltantes" o con el texto del error. No envuelvas la llamada en try/except por miedo a un raise — no lo hay.