Capítulo 2 de 23 10 secciones 18 min

Compartir

Qué puedes calcular con cada columna

Nominal, ordinal, discreta y continua. Y las cuentas que salen sin dar error y no significan nada.

Hay cuatro tipos de variable y cada uno permite unas medidas y prohíbe otras. Nominal son categorías sin orden y solo admiten moda y frecuencias, ordinal son categorías con orden y admiten mediana, discreta son números contables y continua es cualquier valor de un rango. Y lo que a mí me obliga a revisar siempre: el software no conoce esta diferencia. describe() calcula tan tranquilo la media de un número de factura y devuelve 11499,50, que no significa nada.

En el capítulo 1 vimos que las ventas se mueven 14,41% al mes, y que había nueve ciudades donde tenía que haber seis 🙃

Este capítulo arregla eso y contesta una pregunta que parece de manual y es de las más prácticas del libro: ¿qué puedo calcular con cada columna?

Porque tu computadora no lo sabe. Le pides la media de lo que sea y te la da. El problema es que la mitad de esas medias no significan nada, y no hay ningún mensaje de error que te avise 😶

Y dime si te suena: ¿alguna vez reportaste un promedio sin preguntarte si tenía sentido promediarlo? Todas lo hicimos. Este capítulo va de que no vuelva a pasar 😶

Primero la limpieza, que si no todo lo demás miente

Tres cosas por orden.

Uno: las filas repetidas. Se van primero, porque una fila duplicada cuenta dos veces en todas las medidas que vengan después.

import pandas as pd

URL = 'https://missyera.com/static/datasets/ventas-miss-yera.csv'

v = pd.read_csv(URL)
print('filas:', len(v), '| duplicadas enteras:', v.duplicated().sum())

v = v.drop_duplicates()
print('quedan:', len(v))
filas: 3037 | duplicadas enteras: 37
quedan: 3000

37 filas idénticas. No es que se parezcan: son la misma venta escrita dos veces, con el mismo identificador y todo.

Dos: las cuatro Limas.

print(v['ciudad'].value_counts())
ciudad
Arequipa    546
Chiclayo    510
Piura       506
Cusco       496
Trujillo    471
lima        123
Líma        118
Lima        118
LIMA        112
Name: count, dtype: int64

Ahí está la trampa entera: lima, Líma, Lima y LIMA. Para ti son la misma ciudad. Para pandas son cuatro textos distintos, y ninguno se parece más al otro que a Piura.

Se arregla en una línea encadenada:

v['ciudad'] = (v['ciudad'].str.strip().str.lower()
               .str.normalize('NFKD')
               .str.encode('ascii', 'ignore').str.decode('utf-8'))

print(v['ciudad'].value_counts())
ciudad
arequipa    546
chiclayo    510
piura       506
cusco       496
trujillo    471
lima        471
Name: count, dtype: int64

Seis ciudades 🎉 Y Lima pasa de aparentar 123 ventas a tener 471, que la pone empatada con Trujillo.

Lo que hace cada trozo, por si te lo preguntas: strip quita espacios de los bordes, lower pasa todo a minúscula, y ese normalize('NFKD') con el encode/decode es el truco que convierte í en i. Descompone la letra acentuada en letra más tilde y luego tira lo que no sea ASCII.

Tres: los números que llegaron como texto.

print(v.dtypes.head(9))
id_venta      int64
fecha           str
cliente_id      str
ciudad          str
segmento        str
canal           str
categoria       str
unidades      int64
monto           str
dtype: object

monto es str, o sea texto. Y ya sabemos por qué: trae comas decimales al estilo peruano, y pandas ante la duda no toca nada.

v['monto'] = pd.to_numeric(v['monto'].str.replace(',', '.'))
print(v['monto'].dtype, '| media: %.2f' % v['monto'].mean())
float64 | media: 803.76
Árbol para saber qué se puede calcular con una columna: si no guarda números es nominal (moda) u ordinal (mediana) según si hay orden, y si guarda números es discreta cuando es contable y continua cuando no, que es la única que admite media y desviación.
El árbol se recorre en diez segundos y decide todo lo que viene después. La rama de abajo a la izquierda es la que más veces se salta: una media sobre categorías se calcula sin dar error.

Los cuatro tipos, con lo que puedes hacer con cada uno

Ahora la parte que te va a servir para el resto del libro. Cada columna es de uno de estos cuatro tipos 👇

TipoQué esEn este archivoQué puedes calcular
Nominal Categorías sin orden ciudad, segmento, canal, categoria Frecuencias y moda. Nada más.
Ordinal Categorías con orden, pero sin distancia fija satisfaccion (1 a 5) Mediana, percentiles, moda
Discreta Números que se cuentan, sin partes unidades Todo, y la media puede salir con decimales
Continua Cualquier valor dentro de un rango monto, descuento Todo: media, desviación, correlación

La frontera que más se discute es la de ordinal. Satisfacción va de 1 a 5 y tiene orden clarísimo: 5 es mejor que 4. Pero la distancia no es fija. Pasar de 1 a 2 no es lo mismo, para el cliente, que pasar de 4 a 5. Y como no lo es, sumar y dividir es discutible.

Yo la uso así, y te lo digo como criterio práctico y no como ley: la mediana de satisfacción es la medida honesta; la media se puede reportar al lado, pero no se pelea por dos décimas 🤷

Ahora el error de verdad

Pídele a pandas la media de una columna de texto:

v['ciudad'].mean()
TypeError: Cannot perform reduction 'mean' with string dtype

Perfecto, ¿no? Te para en seco. Ese error es tu amigo.

El problema es el caso de al lado, que es el mismo disparate y no para nada:

print(v[['id_venta', 'unidades', 'monto', 'satisfaccion', 'compro']]
      .describe().round(2))
       id_venta  unidades    monto  satisfaccion   compro
count   3000.00   3000.00  3000.00       2769.00  3000.00
mean   11499.50     11.60   803.76          3.01     0.58
std      866.17      5.77   751.99          1.42     0.49
min    10000.00      1.00 -2497.72          1.00     0.00
25%    10749.75      7.00   252.69          2.00     0.00
50%    11499.50     12.00   533.63          3.00     1.00
75%    12249.25     15.00  1068.68          4.00     1.00
max    12999.00     30.00  4236.71          5.00     1.00

Mira la primera columna. La media de id_venta es 11499.50.

Eso es el número de factura promedio. No existe. No significa nada. No se puede hacer nada con él. Y ahí está, con dos decimales, tan formal como los demás 😅

id_venta es un identificador: son números por comodidad, pero funcionan como nombres. Es tan nominal como ciudad. La diferencia es que ciudad se escribe con letras y por eso pandas te frena, y este se escribe con dígitos y por eso pandas calcula.

La lección: que una cuenta salga no quiere decir que signifique algo. El único que sabe qué es cada columna eres tú.

De paso, en esa misma tabla hay dos cosas más que vale la pena que veas:

  • 💸 El mínimo de monto es -2497.72. Hay ventas negativas. Las miramos en el capítulo 6.
  • 🕳️ El count de satisfaccion es 2769 y no 3000. Faltan 231 valores, y la media se calculó ignorándolos sin decir ni pío.

Cómo se detecta el tipo cuando no conoces los datos

Truco de campo, y de los que más uso: cuenta cuántos valores distintos tiene cada columna 🔎

print(v.nunique().sort_values())
compro                      2
canal                       4
segmento                    4
categoria                   5
satisfaccion                5
ciudad                      6
unidades                   30
descuento                 251
fecha_ultima_compra       399
cliente_id                617
fecha                     937
monto_final_facturado    1723
monto                    2964
id_venta                 3000
dtype: int64

Léelo de arriba abajo y el archivo se te ordena solo:

  • 🔢 Lo de arriba, con 2 a 6 valores distintos, es categórico. Da igual que compro y satisfaccion estén escritos con números.
  • 📈 Lo de abajo, con cientos o miles de valores distintos, es continuo o identificador.
  • 🚩 Y hay una bandera roja evidente: id_venta tiene 3000 valores distintos en 3000 filas. Una columna con tantos valores distintos como filas es un identificador, siempre.

Una media que sí significa algo, y mucho

Para que no te quedes con que las medias de columnas 0/1 son sospechosas, mira este caso, que es justo al revés:

print('media de compro:  %.4f' % v['compro'].mean())
print('cuantos compraron: %d de %d' % (v['compro'].sum(), len(v)))
print('proporcion:       %.4f' % (v['compro'].sum() / len(v)))
media de compro:  0.5777
cuantos compraron: 1733 de 3000
proporcion:       0.5777

La media de una columna que solo tiene ceros y unos es la proporción. Exactamente el mismo número.

Y eso es utilísimo: cada vez que quieras un porcentaje de "cuántos cumplen X", conviertes a 0/1 y pides la media. Lo vamos a usar en todo el libro, y en el capítulo 13 esa proporción es la que se compara entre grupos.

O sea que compro es nominal, su media técnicamente no debería significar nada, y significa muchísimo. La regla no es mecánica: es que tienes que saber qué representa el número 🧠

Y dos más, que son este capítulo en estado puro

v['ciudad'].mean()
TypeError: Cannot perform reduction 'mean' with string dtype

Ahí está el capítulo entero en un mensaje: a una nominal no se le calcula la media. No es que quede feo, es que la operación no existe. Y fíjate que pandas te lo dice mirando el tipo, no el significado: lo que le molesta es que sea texto.

v['satisfaccion'].astype(int)
IntCastingNaNError: Cannot convert non-finite values (NA or inf) to integer.Replace or remove non-finite values or cast to an integer typethat supports these values (e.g. 'Int64')

La satisfacción va de 1 a 5 y parece entera, pero le faltan valores. Y un entero no puede estar vacío: no existe el "número entero ausente". Por eso pandas la guarda como decimal en cuanto hay un solo hueco, y por eso pasarla a entero te obliga primero a decidir qué haces con los que faltan 🕳️

Practica 💪

1. ¿Cuántos clientes hay de verdad?

El archivo tiene 3.000 ventas. ¿De cuántos clientes distintos? ¿Y cuántas ventas hace un cliente típico?

print('clientes distintos:', v['cliente_id'].nunique())
print('ventas por cliente: %.2f' % (len(v) / v['cliente_id'].nunique()))
print(v['cliente_id'].value_counts().describe().round(2))
clientes distintos: 617
ventas por cliente: 4.86
count    617.00
mean       4.86
std        2.19
min        1.00
25%        3.00
50%        5.00
75%        6.00
max       14.00
Name: count, dtype: float64

617 clientes y 3.000 ventas: 4,86 ventas por cliente.

Esto cambia cómo hay que leer el archivo entero, y es de las cosas que más se pasan por alto. Las 3.000 filas no son 3.000 clientes independientes: hay uno que aparece 14 veces.

Cuando el mismo cliente sale muchas veces, sus filas se parecen entre ellas más de lo normal, y eso hace que cualquier prueba estadística crea que tiene más información de la que tiene. Es una de las cosas que invalidan análisis y sale en el capítulo 17.

2. Caza las categóricas disfrazadas de números

Escribe algo que recorra las columnas numéricas y te avise de cuáles son sospechosas de ser categorías.

for col in v.select_dtypes('number').columns:
    distintos = v[col].nunique()
    aviso = '  <-- categorica disfrazada' if distintos <= 10 else ''
    print('%-24s %5d distintos%s' % (col, distintos, aviso))
id_venta                  3000 distintos
unidades                    30 distintos
monto                     2964 distintos
descuento                  251 distintos
satisfaccion                 5 distintos  <-- categorica disfrazada
compro                       2 distintos  <-- categorica disfrazada
monto_final_facturado     1723 distintos

Caza las dos que buscábamos. Y fíjate que unidades, con 30 valores, se queda fuera: es discreta de verdad, no una categoría.

El umbral de 10 es mío y es discutible, que quede claro. Sirve como primer filtro para mirar, no como sentencia. Lo que este código hace es ahorrarte abrir 14 columnas a mano 🙌

3. La media que ignora los huecos

La columna descuento tiene vacíos. Calcula su media, y luego calcúlala tratando los vacíos como cero. ¿Cuál está bien?

print('filas totales:      ', len(v))
print('descuentos con dato:', v['descuento'].count())
print('media ignorando huecos: %.4f' % v['descuento'].mean())
print('media con huecos = 0:   %.4f' % v['descuento'].fillna(0).mean())
filas totales:       3000
descuentos con dato: 2405
media ignorando huecos: 0.1252
media con huecos = 0:   0.1004

12,52% contra 10,04%. Una diferencia de dos puntos y medio, decidida enteramente por lo que supongas de 595 celdas vacías.

¿Cuál está bien? Depende de qué signifique el vacío, y eso no está en los datos. Si el sistema deja el campo en blanco cuando no hubo descuento, el vacío es un cero y la buena es 10,04%. Si el campo se llena siempre y esos 595 se perdieron al migrar, el vacío es un desconocido y la buena es 12,52%.

Lo que no puedes hacer es no decidir. Porque mean() decide por ti: ignora los nulos en silencio y te devuelve 12,52% sin avisarte de que se saltó el 20% de las filas.

Esto se pregunta a quien mantiene el sistema. Es la clase de pregunta que distingue a alguien que analiza datos de alguien que ejecuta celdas 😌

4. Fabrica una variable continua: la recencia

Con fecha y fecha_ultima_compra, calcula cuántos días hacía que ese cliente no compraba. Mira bien el resultado antes de darlo por bueno.

for col in ['fecha', 'fecha_ultima_compra']:
    f = pd.to_datetime(v[col], format='%Y-%m-%d', errors='coerce')
    falta = f.isna() & v[col].notna()
    f[falta] = pd.to_datetime(v.loc[falta, col], format='%d/%m/%Y',
                              errors='coerce')
    v[col] = f

dias = (v['fecha'] - v['fecha_ultima_compra']).dt.days
print(dias.describe().round(2))
print('negativos:', (dias < 0).sum())
count    2456.00
mean       72.82
std       190.33
min      -385.00
25%       -65.00
50%        69.00
75%       213.25
max       522.00
dtype: float64
negativos: 904

Aquí hay que parar 🛑

904 valores negativos. O sea 904 ventas donde la "última compra" del cliente ocurrió después de la venta que estamos mirando.

Eso no es un dato raro, es un dato imposible tal como lo estamos leyendo. La explicación más probable es que la columna no sea "la compra anterior a esta" sino "la última compra registrada del cliente hasta hoy", que es un dato del cliente y no de la venta. Con ese significado los negativos son normales: la venta que miramos es vieja y el cliente volvió después.

La conclusión práctica es dura y es la correcta: esta columna no sirve como recencia y hay que preguntar antes de usarla. Si la metes en un análisis tal cual, la mitad de tus filas dice que el cliente compró hace -65 días.

Lo que hicimos aquí, mirar el describe() de una variable recién creada, es lo que evitó publicarlo. Cuesta diez segundos y salva informes 🙏

5. Ordinal: ¿media o mediana?

Compara la satisfacción entre segmentos con las dos medidas. ¿Cuál cuenta mejor lo que pasa?

print(v.groupby('segmento')['satisfaccion']
      .agg(['mean', 'median', 'count']).round(4))
              mean  median  count
segmento
Bodega      2.9603     3.0    655
Horeca      3.0332     3.0    692
Mayorista   2.9927     3.0    684
Minimarket  3.0474     3.0    738

Las medias van de 2,96 a 3,05. Las medianas son todas 3.

Y las dos están contando lo mismo: aquí no pasa nada. La satisfacción no distingue segmentos.

Fíjate en lo fácil que sería hacer el ridículo con esto. Con las medias en la mano, alguien escribe "Minimarket es nuestro segmento más satisfecho, con 3,05 frente al 2,96 de Bodega". Suena a hallazgo. Son nueve centésimas en una escala de 1 a 5, con setecientas filas por grupo.

La mediana, al ser toda 3, te lo deja más difícil de contar mal. Por eso me gusta para ordinales: no te deja fingir precisión que no tienes 🎯

En el capítulo 14 le ponemos número a esto y sale que la diferencia es minúscula incluso comparada con lo que varía la satisfacción dentro de un mismo segmento.

6. La columna que solo existe si la venta se cerró

Saca la media de monto_final_facturado sobre todas las filas y luego solo sobre las que compraron. Explica la diferencia.

print('media sobre las 3000 filas:      %.2f' % v['monto_final_facturado'].mean())
print('media solo sobre los que compraron: %.2f'
      % v.loc[v['compro'] == 1, 'monto_final_facturado'].mean())
print('cuantos ceros:', (v['monto_final_facturado'] == 0).sum())
media sobre las 3000 filas:      481.26
media solo sobre los que compraron: 833.10
cuantos ceros: 1267

481 contra 833. Casi el doble, y las dos son "la media de la misma columna" 🫠

Lo que pasa es que 1.267 filas tienen un cero, y esos ceros no son ventas de cero soles: son ventas que no ocurrieron. La columna solo se llena cuando compro vale 1.

El número que un negocio quiere oír, el ticket promedio, es el de 833,10, y se calcula solo sobre las ventas cerradas. El 481,26 no es el ticket de nada: es una mezcla de tickets y de no-ventas.

Y ojo con esta columna, porque tiene otra trampa peor que la usamos en el libro de machine learning: como solo existe si la venta se cerró, meterla en un modelo que predice si la venta se va a cerrar es hacer trampa. Se llama fuga de información y está contada en el capítulo de fuga del libro de ML.

7. La limpieza completa, en una función

Junta todo lo del capítulo en algo que puedas pegar al inicio de cualquier cuaderno.

def carga_limpia(url):
    """Lee el archivo y deja cada columna en su tipo."""
    v = pd.read_csv(url).drop_duplicates()

    v['ciudad'] = (v['ciudad'].str.strip().str.lower()
                   .str.normalize('NFKD')
                   .str.encode('ascii', 'ignore').str.decode('utf-8'))

    v['monto'] = pd.to_numeric(v['monto'].str.replace(',', '.'))

    for col in ['fecha', 'fecha_ultima_compra']:
        f = pd.to_datetime(v[col], format='%Y-%m-%d', errors='coerce')
        falta = f.isna() & v[col].notna()
        f[falta] = pd.to_datetime(v.loc[falta, col], format='%d/%m/%Y',
                                  errors='coerce')
        v[col] = f

    return v

limpio = carga_limpia(URL)
print(limpio.shape)
print(limpio['ciudad'].nunique(), 'ciudades |',
      limpio['monto'].dtype, '| fechas:', limpio['fecha'].dtype)
(3000, 14)
6 ciudades | float64 | fechas: datetime64[us]

Esta función es la que abre todos los capítulos que vienen. Cópiala 📌

Fíjate en ese falta = f.isna() & v[col].notna(): solo reintenta las fechas que tenían texto y no se pudieron convertir. Sin la segunda condición intentaría rellenar también los huecos de verdad, y esos tienen que seguir siendo huecos 🕳️

8. La ficha de tipos de toda la tabla

Saca de un tirón el tipo que pandas le puso a cada columna y cuántos valores distintos tiene.

for col in v.columns:
    print('%-22s %-16s %5d distintos' % (col, v[col].dtype, v[col].nunique()))
id_venta               int64             3000 distintos
fecha                  datetime64[us]     537 distintos
cliente_id             str                617 distintos
ciudad                 str                  6 distintos
segmento               str                  4 distintos
canal                  str                  4 distintos
categoria              str                  5 distintos
unidades               int64               30 distintos
monto                  float64           2964 distintos
descuento              float64            251 distintos
fecha_ultima_compra    datetime64[us]     399 distintos
satisfaccion           float64              5 distintos
compro                 int64                2 distintos
monto_final_facturado  float64           1723 distintos

Esta tabla es lo primero que yo miro de un archivo que no conozco, y tarda un segundo 📋

Fíjate en las dos columnas juntas, que es donde está la gracia. satisfaccion es float64 y tiene cinco valores distintos: pandas la guarda como decimal y en realidad es ordinal. Y compro es int64 con dos valores, o sea binaria disfrazada de número.

El tipo que pone pandas dice cómo está guardada. El tipo que importa lo decides tú mirando cuántos valores distintos hay y qué significan 🔍

9. Convertir una ordinal en ordinal de verdad

Dile a pandas que el segmento tiene orden, y comprueba que después se puede comparar.

orden = ['Bodega', 'Minimarket', 'Horeca', 'Mayorista']
v['segmento_orden'] = pd.Categorical(v['segmento'], categories=orden, ordered=True)
print(v.groupby('segmento_orden', observed=True)['monto'].median().round(2).to_string())
print()
print('ahora si se puede preguntar por el orden:')
print((v['segmento_orden'] > 'Minimarket').sum(), 'pedidos son de Horeca o Mayorista')
segmento_orden
Bodega         183.26
Minimarket     413.74
Horeca         743.00
Mayorista     1869.26

ahora si se puede preguntar por el orden:
1492 pedidos son de Horeca o Mayorista

Dos cosas cambian y las dos importan 💜

La primera: la tabla sale en el orden del negocio y no en alfabético. Con eso solo, ya se lee que la mediana sube de 183 a 1.869 según el escalón, que es una historia entera.

La segunda: ahora > 'Minimarket' significa algo. Sobre texto suelto esa comparación te habría dado el orden del diccionario, que aquí no quiere decir nada. Convertir una ordinal en ordinal de verdad es una línea y te ahorra errores todo el resto del análisis 🔑

La satisfacción media que no describe a nadie

Y ahora el número más publicado y menos defendible que existe en las empresas. Está en la mitad de los reportes que he visto 😳

La trampa

Reportas la satisfacción media del mes. Sale 3,01 sobre 5, o sea justo en el medio, así que escribes que los clientes están neutrales.

print(round(v['satisfaccion'].mean(), 2))
# 3.01

print(v['satisfaccion'].value_counts().sort_index())
# 1.0    560
# 2.0    537
# 3.0    551
# 4.0    558
# 5.0    563
Qué está mal

Nadie está neutral 😳 Hay 1.097 clientes molestos (1 y 2) y 1.121 contentos (4 y 5). El promedio da 3 porque los dos bandos se cancelan, no porque haya un bando en el medio.

Y hay algo peor de fondo: una escala de 1 a 5 es ordinal. Sabemos que 4 es mejor que 3, pero no que la distancia entre 3 y 4 sea la misma que entre 1 y 2. Y si las distancias no significan nada, sumarlas y dividirlas tampoco.

La media de una escala de satisfacción es de los números más publicados y menos defendibles que hay. Se ve técnica, cabe en una diapositiva y esconde exactamente lo que había que contar.

Lo que sí se reporta: el reparto entero, o el porcentaje de cada extremo. "El 37% puntúa 1 o 2" es un número con el que se puede hacer algo. "La media es 3,01" no.

Comprueba que lo tienes

describe() te devuelve que la media de id_venta es 11499,50. ¿Qué haces?

  • Nada, es un identificador y esa media no significa nada
  • La reporto como el número de factura promedio
  • Reviso si hay un error en los datos
  • La uso para detectar facturas fuera de rango

Lo que te llevas

  • 🧹 Duplicados primero, textos normalizados después, tipos al final. En ese orden, porque cada paso ensucia al siguiente si se hace al revés.
  • 🏙️ Cuatro formas de escribir Lima son cuatro ciudades para el software. strip, lower y normalize lo arreglan en una línea.
  • 📊 Nominal solo admite frecuencias y moda; ordinal, mediana; discreta y continua, todo.
  • 🤖 El software no conoce esa diferencia. describe() te dará la media de un número de factura y se quedará tan tranquilo.
  • 🔎 nunique() es el mejor detector de tipos que hay. Pocos valores distintos, categoría; tantos valores como filas, identificador.
  • 0️⃣ La media de una columna de ceros y unos es la proporción, y esa sí significa muchísimo.
  • 🕳️ mean() ignora los nulos sin avisar. Aquí eran 595 celdas y movían el descuento medio dos puntos y medio.

Y si de todo el capítulo te llevas una sola frase, que sea esta:

Tu computadora calcula la media de lo que sea. Decidir si eso significa algo es tuyo.

Qué viene ahora

En el capítulo 3 nos metemos con la medida más usada y peor usada del mundo: la media. Con un caso donde la media dice 803 soles, la mediana dice 533 y la diferencia entre las dos es una decisión de negocio 💰

Practica este capítulo 📓

Todo el código de arriba en un cuaderno que corre de principio a fin, y los ejercicios con una celda vacía para que los hagas tú. Se abre en Google Colab de un clic y no hay que instalar nada. Donde veas %%revisa, escribe tu respuesta y el cuaderno te dice si te salió.

¿Prefieres trabajar en tu máquina? Bájate el cuaderno de práctica o el de soluciones. Todos están también en github.com/soymissyera/MissYeraEjercicios.

¿Le sirve a alguien que conoces?

Pásale el libro. Es gratis, está entero y no pide registro 🐣

Instagram y TikTok no dejan compartir enlaces desde la web: esos dos copian la URL para que la pegues en tu historia.

¿Tienes alguna duda o consulta?