Cada fabricante responde a «¿cuánto cuesta este coche?» con campos distintos. Esta guía enseña a leer los campos reales de varios configuradores y a llevarlos a un esquema común sin mezclar bases fiscales.
Si extraes precios de varios configuradores y los pones en una misma columna, lo más probable es que estés comparando cosas distintas. Un fabricante publica el precio con IVA, otro sin él; uno ya descuenta la promoción y otro muestra el precio de tarifa; algunos incluyen el impuesto de matriculación y otros lo dejan fuera. Si no distingues la base de cada importe, cualquier comparación entre marcas, países o fechas queda contaminada.
Normalizar no consiste en «limpiar» el dato, sino en declarar, para cada importe, qué es: si es de tarifa o con descuento, bruto o neto, con o sin impuestos especiales. Esa declaración es lo que permite usar el dato después en un panel, un modelo de precios o un contrato. Detrás de cada página de marca del hub de configuradores OEM hay un diccionario de campos precisamente para esto.
Antes de mirar campos conviene fijar el vocabulario. Hay tres ejes independientes y cada importe de un configurador ocupa una posición en cada uno:
La mejor forma de ver la diferencia es mirar filas verdaderas. La tabla recoge una fila de cada marca, procedente de las muestras de nuestros actores para el mercado español, en euros. No son cifras agregadas ni comparativas: son los campos tal como los entrega cada configurador.
| Marca / fila | Campo | Valor | Qué representa |
|---|---|---|---|
| BMW 118d (ES) | gross_list_price | 42768.1 | Precio de lista bruto |
| BMW 118d (ES) | net_list_price | 34010.4 | Precio de lista neto |
| BMW 118d (ES) | total_taxes | 8757.678 | Impuestos entre bruto y neto |
| BMW 118d (ES) | emission_tax_pct | 0.0475 | Porcentaje por emisiones |
| Kia EV6 Air (ES) | msrp_before_discount | 48995.01 | Precio de lista antes del descuento |
| Kia EV6 Air (ES) | discount_amount | 13465 | Descuento en euros |
| Kia EV6 Air (ES) | msrp_dc_price | 35530.01 | Precio tras descuento |
| Kia EV6 Air (ES) | is_net_price | False | El importe mostrado no es neto |
| Kia EV6 Air (ES) | net_price | 29363.64 | Neto del precio tras descuento |
| Toyota Aygo X Cross (ES) | price_list | 27800 | Precio de lista |
| Toyota Aygo X Cross (ES) | price_discount | 3300 | Descuento |
| Toyota Aygo X Cross (ES) | price_with_discount | 24500 | Precio tras descuento |
| Toyota Aygo X Cross (ES) | price_net | 22975.21 | Neto del precio de lista |
| Toyota Aygo X Cross (ES) | price_tax | 4824.79 | Impuesto del precio de lista |
En BMW el neto y el bruto son campos hermanos y la diferencia entre ambos se publica en total_taxes. En esa fila, 8757.678 dividido entre el neto 34010.4 da 0.2575, es decir, el 21 % de IVA más el 4,75 % de emission_tax_pct. Conclusión práctica: total_taxes no es solo IVA; agrupa IVA e impuesto por emisiones, y si lo restas pensando que es IVA, obtendrás un neto equivocado.
En Kia, la estructura es otra: hay un precio de lista, un descuento y un precio final, más un indicador booleano, is_net_price, que avisa de si el importe mostrado es neto. Aquí la comprobación es aritmética: 48995.01 menos 13465 da 35530.01, y 35530.01 dividido entre 1,21 da 29363.64. El campo net_price es, por tanto, el neto del precio tras descuento, no el de lista.
Toyota es la trampa más fina. price_net vale 22975.21, que es el neto del precio de lista (27800 entre 1,21), no del precio con descuento. El neto tras descuento aparece en otro campo, price_ex_vat, con 20247.93. Dos marcas con un campo llamado «neto» y dos bases distintas: de ahí que nunca se deba mapear por el nombre del campo, sino por lo que cada campo representa verificado contra una fila.
El objetivo es un esquema en el que cada importe lleve su base explícita. Una propuesta mínima, que usamos como punto de partida en los proyectos de normalización de datos, es la siguiente:
| Campo común | Significado | Cómo se obtiene |
|---|---|---|
| price_list_gross | Precio de lista con IVA | BMW: gross_list_price; Kia: msrp_before_discount; Toyota: price_list |
| discount_amount | Descuento en moneda local | Kia: discount_amount; Toyota: price_discount; si no existe, nulo |
| price_final_gross | Precio final con IVA | Kia: msrp_dc_price; Toyota: price_with_discount |
| price_final_net | Precio final sin IVA | Kia: net_price; Toyota: price_ex_vat; BMW: net_list_price |
| vat_rate | Tipo de IVA aplicado | Campo de la fuente o derivado y marcado como derivado |
| registration_tax_amount | Impuesto de matriculación, si se conoce | Solo si la fuente lo separa; si no, nulo con bandera |
| price_basis_flag | Calidad de la base fiscal | ok, derived o unknown |
Una regla que ahorra problemas: conserva siempre el campo original junto al normalizado y añade una bandera de calidad en lugar de descartar filas. Si el neto se ha derivado dividiendo entre el IVA, márcalo como derivado; si la fuente no deja separar el impuesto de matriculación, deja el campo nulo y márcalo. Quien consume el dato decide si acepta las filas derivadas. Algunos de nuestros actores ya hacen esto de forma nativa: Toyota entrega tax_calculation_status y price_quality, y Volkswagen entrega price_net_status y registration_tax_status.
Esta filosofía, marcar y dejar pasar, evita el error opuesto, que es filtrar en silencio y que el analista nunca sepa que faltaban datos. Con la bandera, un panel puede mostrar la cobertura de neto verificado frente a derivado, y un modelo puede decidir si excluye las derivadas.
La normalización no es solo de precios. Para comparar coches eléctricos con híbridos y de combustión hace falta clasificar la propulsión, y la tentación es detectarla por el nombre del modelo o de la versión. Es un error clásico. Si buscas la subcadena «ev» en el texto, una versión llamada «Clio evolution» se clasifica como eléctrica, igual que cualquier nombre que contenga «ev» en cualquier posición, desde «Level» hasta «Revolution».
La solución tiene tres capas. Primera: usa los campos de combustible o propulsión que entrega el configurador, como fuel_type en BMW, fuel_code e is_hybrid en Toyota o engine_category_name, antes que el nombre comercial. Segunda: si hay que recurrir al texto, tokeniza y compara palabras completas, con límites de palabra, nunca subcadenas. Tercera: guarda la señal que usaste, por ejemplo propulsion_source = fuel_field | token | unknown, para poder auditar después las clasificaciones inciertas. Y una prueba unitaria con el caso «Clio evolution» evita que el error vuelva con un cambio de código.
Resumido en un orden de trabajo que puedes seguir:
Cada marca tiene su página con cobertura, filas reales y diccionario de campos. Para los ejemplos de esta guía: BMW, Kia, Toyota y Dacia y Renault, esta última con price_retail, price_type y price_without_tax. El hub comercial es datos de precios de coches nuevos, y si quieres recibir los datos ya homogeneizados, puedes pedir un dataset normalizado.
Porque cada configurador publica el importe con una base distinta: con o sin IVA, de tarifa o con descuento, con o sin impuesto de matriculación. Hasta que no declaras la base de cada campo y la llevas a un esquema común, la comparación mezcla conceptos.
El PVP o precio de lista es el importe de tarifa con IVA; el neto es ese importe sin IVA, y el precio con descuento es el que resulta tras aplicar la promoción del fabricante. Son tres ejes distintos y un mismo campo puede combinar dos de ellos, como el neto de un precio ya descontado.
No. Depende del configurador y del país. Algunos lo integran en el precio mostrado y otros lo dejan fuera o solo publican un porcentaje, como `emission_tax_pct` en BMW. Por eso el esquema común lo trata como campo opcional con bandera de calidad.
No detectes la propulsión por subcadenas del nombre: «Clio evolution» contiene «ev» y no es un eléctrico. Usa los campos de combustible de la fuente, y si debes analizar texto, compara palabras completas y registra qué señal usaste.
Sí. Además de las muestras y los actores de cada marca, existe el servicio de normalización, que entrega un esquema común con bandera de calidad. Puedes pedir marcas, mercados y periodo desde la página de datasets.
Descarga una muestra real de hasta 100 filas, ya saneada, o cuéntanos qué fuentes necesitas.