Análisis comparativo de mercados usados. Autos alemanes y franceses en el segmento B y C

Hola Habr!

En esta publicación, quería compartir la experiencia de usar varias herramientas de Python para un análisis comparativo del mercado de autos usados ​​en Europa usando el ejemplo de Alemania y Francia.

imagen

Desde el punto de vista de la implementación, todo será bastante vainilla. El zoológico de las tecnologías utilizadas es algo redundante, porque era un fin en sí mismo; quería probarlo.

Antecedentes La idea de realizar dicho análisis me visitó una vez cuando estaba hojeando un sitio de anuncios franceses. Claramente tuve la sensación de que el Citroën C3 era un automóvil extremadamente pobre, que se deprecia en un 20 por ciento anual, pero el Opel Corsa es casi inmortal, por lo que su precio no cambia con la edad (o subirá tan bien Rolex). Fue una observación divertida, dado que los alemanes consideraban que Corsa en un adulto era un signo de un fiasco en la implementación profesional. E incluso hubo bromas sobre el hecho de que en 10 años cualquier automóvil se convierte en un Opel. En ausencia del Trabant de los alemanes occidentales, el papel de Zaporozhets en el folklore alemán fue realizado por esta marca en particular. C3, por lo que sé, no está particularmente representado en Rusia, pero es útil saber que es el heredero espiritual del clásico 2CV de la imagen del título, el legendario auto que perdió Internet durante un par de años (en producción antes de 1989) y le ofreció al conductor una increíble potencia de nueve caballos de fuerza.

Entonces, ponte manos a la obra. Para obtener estadísticas, necesita una fuente con una muestra suficiente. En Alemania, este autoscout24.de en Francia es el mejor que he encontrado por la cantidad de anuncios: www.lacentrale.fr ( existe la versión francesa de scout, pero es menos popular).

Seleccionaremos según la clase B como la más popular y en la que surgió la pregunta inicial (con una pequeña entrada en la clase C). Para recopilar datos, elegiremos aquellos modelos para los que haya datos de los últimos 10 años y para los que haya al menos 1000 anuncios en ambos sitios. De lo contrario, la muestra será muy ruidosa.

Si desea obtener una persona sana de minería de datos, autoscout ofrece una API RESTful si se registra y obtiene una clave.

Por supuesto, no hice esto y comencé a extraer el fumador, de frente a través de un navegador sin cabeza.

Smoker Mining se parecía a esto: en función de los filtros deseados (que se describen a continuación), formamos una cadena de consulta, la pasamos como una dirección al navegador sin cabeza PhantomJS (desde que lo instalé, se ha suspendido por alguna razón).

Desde lo no obvio en esta etapa, agregué la expectativa de cargar un elemento con una clase característica, que contenía datos sobre el número de opciones para la solicitud correspondiente.

with io.open("dump.html", "w", encoding="utf-8") as f: f.write(html) try: element = WebDriverWait(browser, 20).until( EC.presence_of_element_located((By.CLASS_NAME, "cl-filters-summary-counter")) ) # wait until element with summry statistics is present or drop after 20 sec 

El html generado en el navegador se alimenta al analizador BeautifulSoup y buscamos en él un elemento que contenga la figura de los resultados encontrados.

 value = bsObj.findAll("span", {"class": "cl-filters-summary-counter"})[0].text value = value.replace(u'\xa0', u' ') # removes delimeter if results exceed 1000 

Como puede suponer, la solicitud generada incluía el modelo, un pequeño precio y rango de edad, es decir, había muchas solicitudes, con el número de solicitudes superiores a 500 el servidor interrumpió la conexión. Si desea resolver el problema de manera hermosa, es mejor acceder a dichos servicios a través de servidores proxy que se cambian a lo largo del camino (y si tiene una clave API, entonces no es necesario). En Habré hay un artículo inteligente sobre cómo trabajar a través de un proxy. Resolví el problema de baja tecnología: el precio sigue una ley lineal con la edad, así que calculé el alcance de esta línea y limité las solicitudes a solo + .- 30-50 por ciento del precio lineal, e introduje pausas de 10 segundos entre las solicitudes. Eso fue suficiente para no ser prohibido. La recopilación de datos para un modelo tardó aproximadamente media hora en parpadear silenciosamente en la consola.

Algunas palabras sobre los filtros. Para obtener una selección informativa, apliqué los siguientes filtros:

  • Todos los automóviles vienen en configuraciones de 4-5 puertas (Kors, Klio y algunos de los modelos presentados tienen opciones de 3 puertas más baratas).
  • Todos los autos se toman con 4-5 asientos: esta es una característica separada de la anterior, porque Clio, C3 y 308 tienen una versión Société (Entreprise) y hay bastantes en el mercado: estos son autos de servicio de todos los electricistas y montadores, hay una caja en lugar del asiento trasero para basura, y cuestan menos por un par de kiloeuvres ceteris paribus.
  • La potencia del motor está limitada a 129 hp. Porque más adelante en este segmento comienzan las versiones cargadas y los precios no corresponden en absoluto a su modesto estado. Si repite el Achtung, un autoscout en la dirección usa energía no en caballos de fuerza, sino en kilovatios.

Los motores y las cajas de cambios no están especializados, pero en el 99% son mecánicos, y en el caso de Francia, hay una gran cantidad de diesel allí, simplemente porque se promovió allí 10 años antes del dieselgate. Y ahora quieren trasplantar a todos con él, desde el disgusto por la inconstancia de la moral del gobierno, los franceses por segunda semana se entregan a dos queridos juegos nacionales: una huelga y un incendio provocado de automóviles.

Los datos se recopilan, distribuidos por modelo en hojas en archivos de Excel (¡qué datos sin Excel, qué eres! Gracias openpyxl , por la conveniencia de cambiar). Para la visualización, todos los datos de todos los modelos se resumen en un archivo CSV.

Para la visualización, quería presentar una interfaz web simple. En principio, la versión actual no requiere un backend. Hay pocos datos, el procesamiento es rudimentario, puede volcar todo con un JSON largo junto con los gráficos y procesarlo en el lado del cliente. Pero quería probar el servidor con la intención de usarlo más tarde para tareas con cálculos no tan triviales. Y no sé cómo usar JS, así que tendría que atormentarme con el lado del cliente, y el servidor también se puede montar en Python, ya que hay herramientas.

Para implementar el servidor, me atormentaron entre el bokeh con el que había jugado antes y el paquete Plotly + Dash. En una serie de tareas anteriores, estaba muy satisfecho con el bokeh, especialmente porque se puede incrustar en un Jupyter Notebook (con Jupyter Labs, no es tan simple) y el hecho de que es bastante fácil organizar componentes interactivos dentro de los notebooks sin iniciar el servidor bokeh (). Bokeh es la puerta de entrada al mundo de d3.js para aquellos que no saben cómo usar JS.

Para esta tarea, decidí usar el paquete Plotly + Dash (este último es la puerta de entrada al mundo React para aquellos que no saben cómo usar JS). Es más probable que la elección lo intente. Como puede ver en la comparación , la diferencia no es fundamental

Procedemos a la implementación de la interfaz.

Estamos levantando nuestro CSV, empujándolo sobre un par de marcos de datos.

Para diseñar la página correctamente y usar un diseño receptivo, habilitamos CSS local.

 app = dash.Dash(__name__, static_folder='assets') # resource folder app.scripts.config.serve_locally = True app.css.config.serve_locally = True 

A continuación, creamos el diseño más simple usando una tabla de dos columnas, 6 de 12 estándar para diseños adaptativos.

 app.layout = html.Div([ # include custom local css to allow two-column responsive html.Link(href='/assets/twocolumns_dash.css', rel='stylesheet'), html.Div([ # row div html.Div([ # column div html.H3('Average'), dcc.Graph(id='market-app', ), html.H4('Select model'), dcc.Dropdown(id='model_pick', options=model_options, value=None, multi=True) ], className="six columns"), html.Div([ # column div html.H3('Distribution'), dcc.Graph(id='market-app2', ), html.H4('Select year'), dcc.Slider( id='year-slider', min=years.min(), max=years.max(), value=years.min(), step=None, marks={str(year): str(year) for year in years} ) ], className="six columns"), ], className="row") ]) 

Los controles se implementan sin pretensiones, de las características: puede haber muchas entradas y solo una salida (por ejemplo, el gráfico de la izquierda acepta datos del menú desplegable y del control deslizante del año, pero solo un elemento puede actualizarse, esta es una característica Dash, se necesitarán muletas para evitar).

 @app.callback(Output('market-app2', 'figure'), [Input('model_pick', 'value'), Input('year-slider', 'value')]) def update_figure_dist(selected_models, year_picked): traces = [] for model in selected_models: traces.append(go.Bar( x=df_filtered.loc[model, year_picked, :].index.values.tolist(), y=df_filtered.loc[model, year_picked, :]['results'].values.tolist(), name=model )) return { 'data': traces, 'layout': go.Layout( xaxis={'title': 'price'}, yaxis={'title': 'offers'}, hovermode='closest', legend=dict(orientation="h", xanchor="center", y=1.2, x=0.5) ) } 

Interfaz preparada: http://eu-carmarket.herokuapp.com/

Para datos alemanes, entre paréntesis está (DE) para Francia (FR).

A la izquierda vemos los precios de todo el período promediados cada año. En adelante, todos los precios en euros, de acuerdo con las normas de publicación en sitios web, los precios incluyen el IVA. A la derecha está la distribución de ofertas por precio en el año seleccionado. La distribución era ruidosa para muchos modelos, por lo que al construirla se alisa sobre los vecinos más cercanos con un núcleo de 5 elementos (al mirarla decidí no tomar modelos con menos de 1000 anuncios)

Entonces, ¿qué vemos en los datos?

Respondiendo a una pregunta que motivó el estudio, no, el Citroen no se deprecia a una velocidad terrible en comparación con el atemporal Corsa.

imagen

La fuerte diferencia de precios en 2017 no es la fuerte depreciación principal de los Citroens en el primer año. Este es en realidad su aumento de precio con la transición a una nueva generación. Ahora, en lugar de homologar al viejo Citroën 2CV, se parecen más a la contraparte Mini, con puntos de mira de moda para el crossover: jóvenes elegantes y de moda.

Si toma un modelo, la diferencia en los mercados alemán y francés es impactante porque no existe, ni en valores ni en la tasa de depreciación (aunque un automóvil no destrozado de más de 2 años en Francia se encuentra solo si se almacena con un garaje cerrado).

imagen

imagen

imagen

Si toma el mercado, que es popular entre la gente de TI rusa por mudarse de Holanda, entonces debe pagar un 20 por ciento al precio alemán. A pesar del hecho de que no hay fronteras aduaneras entre países de Europa, no funcionará simplemente transportar un automóvil comprado si no pasa como cosas personales que se mueven con por ti Esto requiere que vivas en el país anterior por más de seis meses. De lo contrario, todos los beneficios previstos se eliminarán de usted cuando intente registrar el automóvil.

Si compara los modelos en una gran pila, puede ver varias observaciones interesantes. Después de 10 años, todo converge en aproximadamente un punto, aunque la depreciación de Peugeot, Mazda o Seat es más fuerte que la de Volkswagen Polo, Opel Meriva o Skoda Fabia. Entonces, sí, después de 10 años, cualquier automóvil se convierte en Opel, pero no en Corsa, solo los favoritos como C3 se convierten en Corsa.

imagen

La tasa de depreciación no depende significativamente del modelo. Y del país. Pequeñas desviaciones de la uniformidad lineal universal (por ejemplo, Renault Megane
en 2016, Ford Fiesta en 2017) es simplemente un cambio de generación de modelos.

imagen

imagen

Dado que la depreciación en este caso no es un concepto físico, no significa que los autos estarán en la misma condición. En francés, habrá lados arrugados, abrasiones, parachoques rotos, espejos envueltos en cinta adhesiva y un legado de miles de kilómetros de distancia con un juego de damas. Pero los franceses están convencidos de que el grado de depreciación es el mismo que el de los alemanes y pagan de acuerdo con sus creencias. Pero para persuadir a los alemanes a comprar usados un coche de las manos cariñosas de los conductores y mecánicos franceses: ¿mentirán?

En cuanto a los precios en comparación con Rusia. Hay algún problema con el hecho de que muchos de los modelos descritos no se venden en Rusia. De las pocas características comunes para ambos mercados, puede encontrar el nuevo Polo en el sitio web de Volkswagen (aunque en Rusia es un sedán y en Europa un hatchback). En Rusia, cuesta 8300 nuevos, en Alemania es nuevo desde 13500, y para 8300 será 2012 (fuera de la tabla de Holanda mencionada - 16200 nuevos). Una buena comparación se puede representar en todas partes Kia Rio: Rusia - 9000, Alemania - 11950 (dumping obvio contra el autopatriotismo alemán), Francia - 13700, Holanda - 19950 (Ja-ja, un lamas y medio para un Kirusha al precio de Volkswagen Tiguan / Hyundai Tussan / Nissan X -trail: abraza, llora y recuerda cómo pedalear la bicicleta).

Source: https://habr.com/ru/post/es433448/


All Articles