Analyse comparative des marchés utilisés Voitures allemandes et françaises dans le segment B et C

Bonjour, Habr!

Dans ce post, je voulais partager l'expérience de l'utilisation de plusieurs outils python pour une analyse comparative du marché des voitures d'occasion en Europe en utilisant l'exemple de l'Allemagne et de la France.

image

Du point de vue de la mise en œuvre, tout sera assez vanillé. Le zoo des technologies utilisées est quelque peu redondant, car c'était une fin en soi - je voulais le tester.

Contexte. L'idée de mener une telle analyse m'a visité une fois alors que je feuilletais un site de publicités françaises. J'ai clairement eu le sentiment que la Citroën C3 était une voiture extrêmement pauvre, qui se déprécie de 20% par an, mais l'Opel Corsa est presque immortelle, donc son prix ne change pas avec l'âge (ou il montera aussi bien Rolex). C'était une observation amusante, étant donné que les Allemands considéraient la Corsa chez un adulte comme un signe de fiasco dans la mise en œuvre professionnelle. Et même il y avait des blagues sur le fait qu'en 10 ans, toute voiture se transforme en Opel. En l'absence du Trabant des Allemands de l'Ouest, le rôle des Zaporozhets dans le folklore allemand a été joué par cette marque particulière. C3, pour autant que je sache, n'est pas particulièrement représentée en Russie, mais il est utile de savoir qu'il s'agit de l'héritier spirituel de la 2CV classique de la photo de titre, la voiture légendaire qui a raté Internet pendant quelques années (en production avant 1989) et a offert au conducteur une incroyable puissance de neuf chevaux.

Alors, passez aux choses sérieuses. Pour obtenir des statistiques, vous avez besoin d'une source avec un échantillon suffisant. En Allemagne, cet autoscout24.de en France est le meilleur que j'ai rencontré par le nombre d'annonces - www.lacentrale.fr (la version française de scout existe, mais est moins populaire).

Nous choisirons selon la classe B comme la plus populaire et dans laquelle la question initiale s'est posée (avec une petite entrée dans la classe C). Pour collecter des données, nous choisirons les modèles pour lesquels il existe des données pour les 10 dernières années et pour lesquels il y a au moins 1000 annonces sur les deux sites. Sinon, l'échantillon sera très bruyant.

Si vous souhaitez obtenir une datamining de personne en bonne santé - la recherche automatique propose une API RESTful si vous vous inscrivez et obtenez une clé.

Bien sûr, je ne l'ai pas fait et j'ai commencé à extraire le fumeur - de front via un navigateur sans tête.

L'extraction de fumeurs ressemblait à ceci - sur la base des filtres souhaités (décrits ci-dessous), nous formons une chaîne de requête, la transférons en tant qu'adresse au navigateur sans tête PhantomJS (depuis que je l'ai installé, il a été suspendu pour une raison quelconque).

Du non-évident à ce stade - j'ai ajouté l'attente de charger un élément avec une classe caractéristique, qui contenait des données sur le nombre d'options pour la demande correspondante.

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 

Le code HTML généré dans le navigateur est envoyé à l'analyseur BeautifulSoup et nous y recherchons un élément contenant la figure des résultats trouvés.

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

Comme vous pouvez le deviner, la demande générée comprenait le modèle, un petit prix et une tranche d'âge, c'est-à-dire qu'il y avait beaucoup de demandes, avec un nombre de demandes supérieur à 500, le serveur a rompu la connexion. Si vous voulez résoudre le problème magnifiquement, il est préférable d'accéder à ces services via des procurations qui sont modifiées en cours de route (et si vous avez une clé API, vous n'en avez pas besoin). Sur Habré, il y a un article intelligent sur la façon de travailler via un proxy. J'ai résolu le problème de la basse technologie - le prix suit une loi linéaire avec l'âge, j'ai donc compris l'étendue de cette ligne et limité les demandes à seulement + .- 30-50 pour cent du prix linéaire, et introduit des pauses de 10 secondes entre les demandes. C'était suffisant pour ne pas être interdit. La collecte de données pour un modèle a pris environ une demi-heure pour clignoter silencieusement dans la console.

Quelques mots sur les filtres. Pour obtenir une sélection informative, j'ai appliqué les filtres suivants:

  • Toutes les voitures sont disponibles en configurations 4-5 portes (Kors, Klio et quelques-uns des modèles prĂ©sentĂ©s ont des options 3 portes moins chères).
  • Toutes les voitures sont prises avec 4-5 sièges - c'est une caractĂ©ristique distincte de la prĂ©cĂ©dente, car Clio, C3 et 308 ont une version SociĂ©tĂ© (Entreprise) et il y en a beaucoup sur le marchĂ© - ce sont des voitures de service de tous les Ă©lectriciens et installateurs, il y a une boĂ®te Ă  la place de la banquette arrière pour la malbouffe, et ils coĂ»tent moins cher de quelques kiloeuvres ceteris paribus.
  • La puissance du moteur est limitĂ©e Ă  129 ch. Parce que plus loin dans ce segment, les versions payantes commencent et les prix ne correspondent pas du tout Ă  leur modeste statut. Si vous rĂ©pĂ©tez l'Achtung - une recherche automatique dans l'adresse utilise la puissance non pas en chevaux-vapeur, mais en kilowatts.

Les moteurs et boîtes de vitesses ne sont pas spécialisés, mais à 99% ce sont des mécaniciens, et dans le cas de la France, il y a beaucoup de diesel là-bas, tout simplement parce qu'il y a été promu 10 ans avant le dieselgate. Et maintenant, ils veulent transplanter tout le monde avec lui, du chagrin devant une telle inconstance de la morale gouvernementale, les Français s'adonnent à leur deuxième passe-temps national préféré depuis deux semaines - la grève et l'incendie criminel de voitures.

Les données sont collectées, présentées par modèle dans des feuilles dans des fichiers Excel (quelles données sans Excel, que faites-vous! Merci openpyxl - pour la commodité du décalage). Pour la visualisation, toutes les données de tous les modèles sont résumées dans un fichier CSV.

Pour la visualisation, je voulais déposer une interface web simple. En principe, la version actuelle ne nécessite pas de backend. Il y a peu de données, le traitement est rudimentaire, vous pouvez tout vider avec un long JSON avec les graphiques et le traiter côté client. Mais je voulais tester le serveur avec un œil pour l'utiliser plus tard pour des tâches avec des calculs pas si triviaux. Et je ne sais pas comment utiliser JS, donc je devrais me tourmenter avec le côté client, et le serveur peut également être monté sur python, car il existe des outils.

Pour implémenter le serveur, j'ai été tourmenté entre le bokeh que j'avais bricolé avant et le bundle Plotly + Dash. Dans un certain nombre de tâches passées, j'étais très satisfait du bokeh, en particulier parce qu'il peut être intégré dans un bloc-notes Jupyter (avec Jupyter Labs, ce n'est pas si simple) et du fait qu'il est assez facile d' organiser des composants interactifs dans des blocs-notes sans démarrer le serveur bokeh (). Bokeh est la passerelle vers le monde de d3.js pour ceux qui ne savent pas utiliser JS.

Pour cette tâche, j'ai décidé d'utiliser le bundle Plotly + Dash (ce dernier est la passerelle vers le monde React pour ceux qui ne savent pas utiliser JS). Le choix est plus susceptible d'essayer. Comme vous pouvez le voir sur la comparaison - la différence n'est pas fondamentale

Nous procédons à l'implémentation de l'interface.

Nous remontons notre CSV, le poussant sur quelques trames de données.

Afin de styliser correctement la page et d'utiliser une conception réactive, nous activons le CSS local.

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

Ensuite, nous créons la mise en page la plus simple en utilisant un tableau de deux colonnes, 6 sur 12 standard pour les mises en page adaptatives.

 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") ]) 

Les contrôles sont mis en œuvre sans aucune prétention, des fonctionnalités - il peut y avoir de nombreuses entrées et une seule sortie (par exemple, le graphique de gauche accepte les données du menu déroulant et du curseur de l'année, mais un seul élément peut être mis à jour, c'est une fonctionnalité Dash, des béquilles seront nécessaires pour contourner).

 @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) ) } 

Interface prĂŞte - http://eu-carmarket.herokuapp.com/

Pour les données allemandes, entre parenthèses est (DE) pour la France (FR).

Sur la gauche, nous voyons les prix pour toute la période en moyenne sur chaque année. Ci-après, tous les prix en euros, selon les règles de publication sur les sites Internet - les prix incluent la TVA. À droite, la répartition des offres par prix au cours de l'année sélectionnée. La distribution était bruyante pour de nombreux modèles, donc lors de la construction, elle est lissée sur les voisins les plus proches avec un noyau de 5 éléments (c'est en le regardant que j'ai décidé de ne pas prendre de modèles avec moins de 1000 annonces)

Alors que voyons-nous dans les données?

Répondant à une question qui a motivé l'étude - non, la Citroën ne se déprécie pas à une vitesse terrible par rapport à l'intemporelle Corsa.

image

La forte différence de prix en 2017 n'est pas la principale forte dépréciation des Citroën la première année. Il s'agit en fait de leur hausse de prix avec le passage à une nouvelle génération. Maintenant, au lieu d'homologuer la vieille Citroën 2CV, ils ressemblent plus à la Mini homologue, avec un réticule à la mode pour le crossover - une jeunesse élégante et à la mode.

Si vous prenez un modèle, la différence sur les marchés allemand et français est choquante car elle n'existe pas, ni en valeur ni en taux d'amortissement (bien qu'une voiture non accidentée de plus de 2 ans en France ne se retrouve que si elle est entreposée avec un garage fermé).

image

image

image

Si vous prenez le marché, qui est populaire auprès des spécialistes informatiques russes pour déménager la Hollande, vous devez payer 20% du prix allemand. Bien qu'il n'y ait pas de frontières douanières entre les pays européens, vous ne pourrez pas transporter une voiture achetée comme ça si elle ne passe pas comme des objets personnels qui se déplacent avec par vous. Cela vous oblige à vivre dans le pays précédent pendant plus de six mois. Sinon, tous les avantages escomptés vous seront retirés lorsque vous tenterez de mettre la voiture en circulation.

Si vous comparez les modèles dans une grande pile, vous pouvez voir plusieurs observations intéressantes. Après 10 ans, tout converge vers environ un point, bien que la dépréciation de Peugeot, Mazda ou Seat soit plus forte que Volkswagen Polo, Opel Meriva ou Skoda Fabia. Alors oui, après 10 ans, n'importe quelle voiture devient Opel, mais pas Corsa, seuls les favoris comme C3 deviennent Corsa.

image

Le taux d'amortissement ne dépend pas significativement du modèle. Et du pays. Petits écarts par rapport à l'uniformité linéaire universelle (par exemple Renault Megane
en 2016, Ford Fiesta en 2017) est tout simplement un changement de génération de modèle.

image

image

Étant donné que l'amortissement dans ce cas n'est pas un concept physique, cela ne signifie pas que les voitures seront dans le même état. En français, il y aura des côtés ridés, des abrasions, des pare-chocs ébréchés, des miroirs attachés à du ruban adhésif et un héritage de milliers de kilomètres avec un jeu de dames. Mais les Français sont convaincus que le degré de dépréciation est le même que celui des Allemands et paient conformément à leurs convictions. Mais pour persuader les Allemands d'acheter d'occasion une voiture entre les mains des conducteurs et des mécaniciens français - mentiront-ils?

Concernant les prix par rapport à la Russie. Il y a un problème avec le fait que la plupart des modèles décrits ne sont pas vendus en Russie. Parmi les quelques caractéristiques communes aux deux marchés, vous pouvez trouver la nouvelle Polo sur le site Web de Volkswagen (bien qu'en Russie, il s'agit d'une berline et en Europe d'une berline avec hayon). En Russie, il coûte à partir de 8300 nouveaux, en Allemagne, il est nouveau à partir de 13500, et pour 8300 ce sera 2012 (dans le hors-table de la Hollande mentionnée - 16200 nouveaux). Une bonne comparaison peut être représentée partout Kia Rio: Russie - 9000, Allemagne - 11950 (dumping évident contre l'autopatriotisme allemand), France - 13700, Hollande - 19950 (Ja-ja, un et demi lamas pour un Kirusha au prix de Volkswagen Tiguan / Hyundai Tussan / Nissan X -trail: câlin, pleurer et rappelez-vous comment pédaler le vélo).

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


All Articles