! Willkommen am Beginn einer großen Datenreise, die ich „EDA in Public“ nenne. Für diejenigen, die mich kennen: Ich glaube, der beste Weg, etwas zu lernen, besteht darin, ein reales Downside anzugehen und den gesamten chaotischen Prozess zu teilen – einschließlich Fehlern, Siegen und allem, was dazwischen liegt. Wenn Sie Ihre Pandas- und Datenanalysefähigkeiten verbessern möchten, ist dies die richtige Serie für Sie.

Wir werden als Datenanalysten für ein fiktives, mittelgroßes E-Commerce-Unternehmen fungieren, das ich nenne NovaShop. Sie reichten uns eine rohe, unübersichtliche Vertriebs-CSV-Datei und stellten eine einfache Frage: „Wie geht es uns?“

Das Ziel von Teil 1 ist von grundlegender Bedeutung: Wir bereinigen diesen anspruchsvollen E-Commerce-Datensatz, erforschen seine Grundstruktur und erlernen die EDA-Kernkompetenzen in Pandas, die jeder Datenwissenschaftler täglich nutzt. Diese Serie ist so strukturiert, dass sie Sie von a Anfänger (Teil 1) zu einem fortschrittlich Datenanalyst (Teil 3), Sie können additionally jederzeit einsteigen, wo immer Sie sich gerade befinden.

Bevor wir uns mit dem Code befassen, wollen wir unsere Kernmotivation festlegen. Für NovaShop müssen wir einige einfache, aber wirkungsvolle Fragen beantworten: Welche Produkte generieren den meisten Umsatz? Welche Länder generieren die meisten Umsätze? Finden wir es heraus.

Datensatzübersicht: Auspacken der Verkaufsdaten

Um unsere Analyse für NovaShop zu starten, verwenden wir die UCI On-line-Einzelhandelsdatensatz. Hierbei handelt es sich um einen großartigen, äußerst realistischen, nicht optimierten Datensatz, der alle Transaktionen eines in Großbritannien ansässigen On-line-Einzelhandelsunternehmens außerhalb von Filialen zwischen Ende 2010 und Ende 2011 erfasst.

Dieser Datensatz ist lizenziert unter a Artistic Commons Namensnennung 4.0 Worldwide (CC BY 4.0) Lizenz.

Dies ermöglicht die gemeinsame Nutzung und Anpassung der Datensätze für jeden Zweck, sofern die entsprechende Quellenangabe erfolgt.

Der Datensatz enthält über eine halbe Million Zeilen und ist voller Anomalien, die auch in der realen Welt vorkommen – fehlende Werte, destructive Zahlen und inkonsistente Textformatierung. Genau das wollen wir!

Hier sind die acht Schlüsselspalten, mit denen wir arbeiten werden, und was sie uns aus geschäftlicher Sicht sagen:

  • Rechnungsnr.: Das ist das Rechnungsnummer. Jeder Transaktion wird eine eindeutige 6-stellige Nummer zugewiesen. Wenn der Code mit „C“ beginnt, bedeutet dies a Stornierung (eine Rückkehr).
  • StockCode/Produktcode: Ein eindeutiger 5-stelliger Code, der jedem einzelnen Produkt zugewiesen ist.
  • Beschreibung: Der Identify des Components. Dies erfordert häufig eine Reinigung (zusätzliche Räume, inkonsistente Gehäuse).
  • Menge: Anzahl der gekauften Artikel. Wie viele Einheiten waren professional Transaktion beteiligt? Kann sein Negativ für Rücksendungen.
  • Rechnungsdatum: Datum und Uhrzeit der Transaktion. Dies ist für die spätere Zeitreihenanalyse von wesentlicher Bedeutung.
  • Stückpreis: Produktpreis professional Einheit in Pfund Sterling (GBP). Der Preis eines Artikels. Aufgrund von Fehlern/freien Artikeln kann es manchmal 0 oder negativ sein.
  • KundenID: Jedem registrierten Kunden wird eine eindeutige 5-stellige Nummer zugewiesen. Entscheidend ist, dass dies oft fehlt, was bedeutet, dass wir viele Transaktionen von Gästen haben.
  • Land: Identify des Landes, in dem der Kunde seinen Wohnsitz hat. Dies wäre großartig für die Segmentierung des internationalen Vertriebs.

Werfen wir einen kurzen Blick auf die ersten Zeilen, um zu sehen, womit wir es zu tun haben. Dies ist die Ausgabe von df.head():

Lassen Sie uns den Datensatz in Pandas importieren und sehen, mit wie vielen Zeilen wir es zu tun haben.

import pandas as pd
import numpy as np
df = pd.read_csv(‘On-line Retail.csv’)
df.form

Ausgabe:

(541909, 8)

Das sind ziemlich viele Reihen. Möglicherweise muss ich die Zeilen etwas zerschneiden.

Laden und Schneiden von Daten: Umgang mit Volumen

Für Teil 1 nehmen wir eine 10 % Zufallsstichprobe des vollständigen Datensatzes. Dadurch erhalten wir eine wesentlich überschaubarere Größe – etwa 54.000 Zeilen – und behalten gleichzeitig die Eigenschaften der Originaldaten bei. Dies ist eine gängige und praktische Technik beim Umgang mit Massive-Knowledge-Umgebungen oder beim Fokussieren auf Prototyping.

# Knowledge Loading and Slicing
FILE_PATH = ‘On-line Retail.csv’
SAMPLE_FRACTION = 0.1 # We'll pattern 10% of the information
full_df = pd.read_csv(FILE_PATH, encoding=’unicode_escape’)

# Take a random 10% pattern for sooner processing in Half 1
df = full_df.pattern(frac=SAMPLE_FRACTION, random_state=42).reset_index(drop=True)

Schauen wir uns nun die Kind noch einmal mit an df.form

Ausgabe:

(54191, 8)

Perfekt! Jetzt können wir beginnen.

Erste Dateninspektion: Wir machen uns die Hände schmutzig

Mein erster Schritt wird darin bestehen, herauszufinden, was wir reinigen. Ich muss diese Fragen beantworten

  • Was enthält der Datensatz?
  • Welche Datentypen und Nicht-Null-Zählungen gibt es?
  • Wie sehen die Zahlen aus?

Visuelle Prüfung: df.head() und df.tail()

Wenn ich mir die ersten und letzten paar Zeilen anschaue, kann ich ein paar Dinge bestätigen:

  • Stornierungen und Rücksendungen: Einige sind mir zufällig aufgefallen InvoiceNo Werte beginnend mit ‚C‘und das entsprechende Amount ist negativ. Dies bestätigt, dass Retouren enthalten sind, und für die Umsatzanalyse muss ich sie trennen oder ausschließen.
  • Fehlen: Ich konnte visuell sehen NaN Werte in der CustomerID Spalte, die die Masse der Gasttransaktionen bestätigt.
  • Inkonsistenter Textual content: Ich habe die Spalte „Beschreibung“ auf Leerzeichen überprüft. Anhand der kleinen Stichprobe, die ich erhalten habe, konnte ich es nicht wirklich sagen. Aber es schadet nicht, sie anzusprechen, wenn ich mich mit der Datenbereinigung befasse. Ich könnte auch die Groß- und Kleinschreibung konsistent halten. Es ist immer die beste Vorgehensweise Entfernen Sie alle führenden/nachgestellten Leerzeichen aus allen String-Spalten, um subtile Fehler beim Gruppieren zu vermeiden.
  • Mir sind auch einige Inkonsistenzen bei der Groß- und Kleinschreibung in der Spalte „Land“ aufgefallen. Ich habe ein Land namens EIRE entdeckt. Das bedeutet wahrscheinlich, dass Irland das möglicherweise ändern muss.

Was sind die Datentypen und Nicht-Null-Zählungen? (.data())

Der nächste wesentliche Schritt besteht darin, die Struktur anhand des zu überprüfen .data() Verfahren. Dies verrät mir den Datentyp jeder Spalte und, was am wichtigsten ist, wie viele Nicht-Null-Werte (nicht fehlende) wir haben.

Wichtigste Erkenntnisse

  • Fehlende Werte: Nachdem ich unsere 10 %-Stichprobe genommen hatte, konnte ich eine riesige Lücke erkennen CustomerID. Etwa 25 % der Kunden-IDs fehlen. Mir sind auch ein paar hundert fehlende Werte aufgefallen Description das muss ich ansprechen.
  • Datentypen: Der InvoiceDate Spalte wird immer noch als aufgeführt object (String-)Typ. Muss das in einen richtigen Pandas umwandeln datetime Objekt.CustomerID ist derzeit auch ein schwebenwahrscheinlich weil es diese enthält NaN Werte! Dies ist ein kleines Element, das ich mir merken muss, wenn ich es jemals als echte Integer-ID verwenden möchte.

Wie sehen die Zahlen aus? (.describe())

Als nächstes habe ich verwendet .describe() um eine schnelle statistische Zusammenfassung aller numerischen Spalten zu erhalten (Amount Und UnitPrice).

  • Menge (Amount): Die Mindestmenge beträgt -2472. Dies bestätigt, dass es Renditen gibt, aber die Höhe dieser Mindestpunkte deutet auf eine excessive Ausreißertransaktion hin. Für eine grundlegende Verkaufsanalyse muss ich möglicherweise diese negativen Zahlen und möglicherweise die extremen positiven und negativen Ausreißer herausfiltern.
  • Stückpreis (UnitPrice): Der Mindestpreis beträgt 0. Dies bedeutet, dass einige Produkte kostenlos verschenkt wurden oder Platzhaltereinträge sind. Da ein Produkt bei einem normalen Verkauf einen positiven Preis haben sollte, werden alle Zeilen herausgefiltert, in denen UnitPrice Null oder weniger ist immer die beste Methode zur genauen Berechnung des Umsatzes.

Basierend auf diesen durchgeführten Schnellinspektionen. Diese Daten sind alles andere als sauber. Wir haben mit massiven Fehlern, falschen Datentypen, äußerst problematischen negativen/Null-Werten in unseren numerischen Kernspalten und Textinkonsistenzen zu kämpfen.

Umgang mit fehlenden Werten

Da wir nun wissen, wo unsere Daten fehlen, können wir mit der Diskussion von Strategien für den Umgang mit Nullwerten beginnen. Mir geht es vor allem darum Description Und CustomerID.

Fehlende Beschreibungen

Der Description sagt uns, welches Produkt verkauft wurde, sodass der Verlust die Transaktion bedeutungslos macht. In unserer Stichprobe fehlen in weniger als 1 % der Zeilen Beschreibungen. Es ist sinnvoll, diese Zeilen vollständig wegzulassen, da sie für die Analyse auf Produktebene unbrauchbar sind.

# Drop rows the place the Description is lacking
df.dropna(subset=('Description'), inplace=True)
# checking for null counts
df('Description').isnull().sum()

Ausgabe:

np.int64(0)

Alles klar, perfekt! Alle Nullwerte sind weg.

Fehlende Kunden-IDs

Das Vermisste CustomerIDs (etwa 25 % unserer Stichprobe) sind eine viel größere Sache. Wenn ich sie alle weglasse, verliere ich quick ein Viertel unserer Verkaufsdaten, was NovaShop eine gefährlich verzerrte Sicht auf seinen Gesamtumsatz verschaffen wird.

Für eine einfache Umsatz- und Produktanalyse (das Ziel von Teil 1) benötige ich das nicht wirklich CustomerID. Wir können mit der Analyse für alle Zeilen fortfahren auch ohne eine ID. Wir benötigen die ID nur, wenn wir eine Kundensegmentierung (z. B. eine RFM-Analyse) planen, was ich mir für Teil 2 aufhebe!

Datentypkonvertierung und Duplikatentfernung

Nachdem wir uns nun um die fehlenden Beschreibungen gekümmert haben, beschäftigen sich die nächsten beiden unmittelbaren Probleme mit vollständig duplizierten Zeilen und der Behebung unseres wesentlichen Issues InvoiceDate Spalte.

Korrigieren des Rechnungsdatumstyps

Denken Sie daran, wie .data() zeigte InvoiceDate als Zeichenfolge (object)? Wir müssen dies sofort beheben, damit Pandas weiß, wie es unsere Daten chronologisch sortiert und aggregiert.

# Convert InvoiceDate from object (string) to datetime
df(‘InvoiceDate’) = pd.to_datetime(df(‘InvoiceDate’))

Duplikate entfernen

Wenn zwei Reihen quer identisch sind alle Spalten sind Duplikate und werden unsere Verkaufszahlen künstlich in die Höhe treiben. Lassen Sie uns nach ihnen suchen und sie entfernen.

# Take away Duplicates
num_duplicates = df.duplicated().sum()
print(f”Discovered {num_duplicates} totally duplicated rows.”)

Ausgabe:

Discovered 62 totally duplicated rows

Lassen wir sie fallen

# Take away duplicates, maintaining the primary occasion
df.drop_duplicates(inplace=True)
print(f”Dataframe dimension after eradicating duplicates: {len(df)} rows.”)

Ausgabe:

Dataframe dimension after eradicating duplicates: 53980 rows.

Retouren und Fehler herausfiltern

Unser .describe() Die Methode zeigte uns einige schwerwiegende Warnsignale: destructive Mengen (Retouren) und null/destructive Stückpreise (Fehler/freie Artikel). Für Teil 1 wollen wir rechnen Nettoerlös aus Verkäufenadditionally müssen wir dieses Rauschen herausfiltern.

Umgang mit negativen Mengen und Preisen

Wir behalten nur die Transaktionen bei, bei denen:

  • Amount ist unbedingt größer als Null (alle Rückgaben und Stornierungen werden herausgefiltert).
  • UnitPrice ist unbedingt größer als Null (Fehler und freie Artikel werden herausgefiltert).
# Filter: Maintain solely transactions the place Amount is optimistic (i.e., gross sales, not returns)
df = df(df(‘Amount’) > 0)

# Filter: Maintain solely transactions the place UnitPrice is optimistic (i.e., not free or an error)
df = df(df(‘UnitPrice’) > 0)
print(f”Dataframe dimension after filtering: {len(df)} rows.”)

Ausgabe

Dataframe dimension after filtering: 52933 rows.

Textspalten bereinigen

Lassen Sie uns abschließend die Probleme bei der Textstandardisierung angehen, die uns visuell aufgefallen sind, wie z EIRE Ländercode und etwaige versteckte Leerzeichen darin Description.

  • Leerzeichen entfernen: Wir verwenden .str.strip() um führende/nachgestellte Leerzeichen von beiden zu entfernen Description Und Nation.
  • Land standardisieren: Wir ordnen Inkonsistenzen wie „EIRE“ manuell „Irland“ zu.
# Cleansing Textual content Columns
# Clear Description and Nation columns
df(‘Description’) = df(‘Description’).str.strip()
df(‘Nation’) = df(‘Nation’).str.strip()

# Deal with particular nation title inconsistencies
# EIRE is a standard inconsistency on this dataset for Eire
df(‘Nation’).substitute(‘EIRE’, ‘Eire’, inplace=True)
print(“Textual content columns cleaned and standardized.”)

Characteristic Engineering und erste Einblicke

Die Daten sind jetzt sauber. Jetzt können wir endlich anfangen, die lustigen Fragen zu stellen. Die wichtigste Kennzahl für jeden Verkaufsdatensatz ist der Umsatz. Da unsere ursprünglichen Daten nur haben Amount Und UnitPricewir müssen das konstruieren Einnahmen Kolumne selbst.

Characteristic Engineering: Erstellen des Income Spalte

Der Umsatz einer Transaktion ist einfach die Anzahl der verkauften Artikel multipliziert mit dem Preis jedes Artikels.

df(‘Income’) = df(‘Amount’) * df(‘UnitPrice’)

Erster Einblick: Welche Länder steigern den Umsatz?

Lassen Sie uns unsere sauberen Daten verwenden, um die Frage von NovaShop zu beantworten: „Welche Länder treiben unseren Umsatz voran?“
Wir verwenden eine leistungsstarke Drei-Schritte-Kombination:

  • Gruppe durch die Nation Spalte.
  • Aggregat (Summe) die Income innerhalb jeder Gruppe.
  • Sortieren die Ergebnisse vom höchsten zum niedrigsten Umsatz.
# Group by Nation, sum the Income, and type for the highest 10
top_countries = df.groupby(‘Nation’)(‘Income’).sum().sort_values(ascending=False).head(10)
print(“n — — High 10 Nations by Income (GBP) — -”)
print(top_countries)

Ausgabe:

--- High 10 Nations by Income (GBP) ---
Nation
United Kingdom 941268.661
Netherlands 27435.830
EIRE 26066.000
France 23645.330
Germany 22389.510
Australia 12429.990
Spain 5600.900
Switzerland 5483.890
Hong Kong 3597.850
Belgium 3593.510
Identify: Income, dtype: float64

Die Ausgabe hierfür zeigt typischerweise eine large Dominanz durch Vereinigtes Königreich. Dies ist zu erwarten, da das Unternehmen seinen Sitz im Vereinigten Königreich hat. Die nächsten Länder geben uns einen schnellen Überblick darüber, wo der internationale Fokus von NovaShop liegen sollte.

Abschluss

Wir haben es geschafft. Wir haben einen Rohdatensatz mit einer halben Million Zeilen genommen, ihn aus Gründen der Verwaltbarkeit segmentiert, fehlende Werte bekämpft, Datentypen korrigiert, Fehler herausgefiltert und unsere erste wichtige Geschäftsmetrik berechnet. Die harte, grundlegende Arbeit ist erledigt.

Hier ist eine kurze Zusammenfassung dessen, was wir in Teil 1 erobert haben:

  • Datenüberprüfung: Wir haben verwendet .head(), .data()Und .describe() um entscheidende Probleme wie destructive Preise/Mengen, fehlende Kunden-IDs und das falsche Datum/Uhrzeit-Format zu identifizieren.
  • Datenbereinigung: Wir haben Nullen und Duplikate systematisch entfernt und konvertiert InvoiceDate zu einem richtigen datetime Objekt und filterte Nicht-Verkaufstransaktionen (Retouren und Gratisartikel) heraus.
  • Characteristic-Engineering: Wir haben das Kritische geschaffen Income Spalte.
  • Erster Einblick: Wir haben für NovaShop die 10 umsatzstärksten Länder erstellt und ihnen damit den ersten verwertbaren Datenpunkt aus der Gesamtmenge gegeben.

Der saubere Datensatz ist nun für eine anspruchsvollere Analyse vorbereitet. In Teil 2 werden wir tiefer eintauchen Produktanalyse und Zeitreihenzerlegung. Wir finden heraus, mit welchen Artikeln sich wirklich Geld verdienen lässt, und analysieren, wie sich das Verkaufsvolumen von Stunde zu Stunde und von Monat zu Monat verändert.

Ich freue mich darauf, weiterzumachen! Wenn Ihnen dieser Artikel gefallen hat. Teilen Sie mir dies gerne auf einem dieser Kanäle mit. Ihr Suggestions wird mir sehr viel bedeuten.

Medium

LinkedIn

Twitter

YouTube

Von admin

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert