0Pricing
Pandas & NumPy Academy · Lektion

CSV-Streaming mit chunksize

Lesen Sie eine große CSV-Datei mit pd.read_csv(chunksize=) in Blöcken fester Größe ein, verarbeiten Sie jeden Block und verketten oder akkumulieren Sie die Ergebnisse.

CSV-Streaming mit chunksize ist eine kostenlose Pandas & NumPy Academy-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Pandas & NumPy Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Pandas & NumPy Academy-Kurs umfasst insgesamt 4 Lektionen.

Das Problem mit großen CSV-Dateien

Wenn eine CSV-Datei größer ist als der verfügbare Arbeitsspeicher — etwa eine 50-GB-Logdatei auf einem Rechner mit 16 GB Arbeitsspeicher — schlägt der Aufruf von pd.read_csv('file.csv') mit einem MemoryError fehl oder das System beginnt stark auszulagern, wodurch es unbrauchbar langsam wird. Die Lösung ist das Lesen in Blöcken: Statt die gesamte Datei auf einmal zu laden, verarbeiten Sie sie in Blöcken fester Größe und sammeln die Ergebnisse, ohne jemals alle Daten gleichzeitig im Arbeitsspeicher zu halten.

Der Parameter chunksize in read_csv

Wenn Sie chunksize=N an pd.read_csv() übergeben, wird statt eines DataFrames ein TextFileReader iterator zurückgegeben. Jede Iteration liefert einen DataFrame mit höchstens N Zeilen. Die Datei wird verzögert gelesen — Daten werden erst geladen, wenn Sie den nächsten Block anfordern. Dieser Iterator kann in einer for-Schleife verwendet oder an pd.concat() übergeben werden. Wählen Sie chunksize groß genug für effiziente Ein-/Ausgabe (z. B. 10.000–100.000 Zeilen), aber klein genug, damit der Block bequem in den Arbeitsspeicher passt.

import pandas as pd

# Returns a TextFileReader iterator, NOT a DataFrame
chunks = pd.read_csv('sales_data.csv', chunksize=10000)
print(type(chunks))  # <class 'pandas.io.parsers.readers.TextFileReader'>

for chunk in chunks:
    print(f'Chunk shape: {chunk.shape}')
    # process each chunk independently
    break   # just show the first chunk here

Jeden Block unabhängig verarbeiten

Das häufigste Muster besteht darin, auf jeden Block eine Transformation oder Filterung anzuwenden, die Ergebnisse in einer Liste zu sammeln und sie anschließend zu verketten. Sie können beispielsweise Zeilen filtern, die einer Bedingung entsprechen, Statistiken pro Block berechnen oder nur die benötigten Spalten auswählen. Durch die Arbeit mit Teilmengen belegt nur der aktuelle Block Arbeitsspeicher, während der Rest der Datei unberührt bleibt. Nach der Schleife setzt ein einzelnes pd.concat(results) den finalen DataFrame zusammen.

import pandas as pd

results = []
for chunk in pd.read_csv('orders.csv', chunksize=50000):
    # Keep only high-value orders
    filtered = chunk[chunk['amount'] > 1000]
    results.append(filtered)

# Combine all filtered chunks
high_value = pd.concat(results, ignore_index=True)
print('High-value orders:', len(high_value))

Aggregierte Werte über Blöcke hinweg sammeln

Manchmal müssen Sie überhaupt keine Zeilen speichern, sondern lediglich eine laufende Aggregation berechnen. Verfolgen Sie über die Blöcke hinweg eine laufende Summe, Anzahl oder den Minimal-/Maximalwert, ohne eine Liste von DataFrames aufzubauen. Dies ist das speichereffizienteste Muster, da der Speicherbedarf unabhängig von der Dateigröße konstant bleibt. Berechnen Sie am Ende die endgültige Statistik aus Ihren Akkumulatoren.

import pandas as pd

total_revenue = 0.0
total_rows = 0

for chunk in pd.read_csv('sales.csv', chunksize=100000):
    total_revenue += chunk['revenue'].sum()
    total_rows += len(chunk)

print(f'Processed {total_rows:,} rows')
print(f'Total revenue: ${total_revenue:,.2f}')

dtype angeben, um das Lesen in Blöcken zu beschleunigen

Standardmäßig leitet Pandas die Datentypen der Spalten aus den Daten ab. Dafür muss jeder Block zweimal durchlaufen werden (einmal zum Ermitteln und einmal zum Parsen). Durch die Angabe des Arguments dtype vermeiden Sie diesen Aufwand und verhindern außerdem uneinheitliche Datentypen zwischen den Blöcken. Eine Spalte, die überwiegend Ganzzahlen, aber eine leere Zelle enthält, kann beispielsweise in einem Block als float64 und in einem anderen als object erkannt werden. Durch die explizite Angabe der Datentypen wird das Lesen über alle Blöcke hinweg konsistent und schneller.

import pandas as pd

dtype_map = {
    'order_id': 'int32',
    'customer_id': 'int32',
    'amount': 'float32',
    'category': 'category'
}

for chunk in pd.read_csv('orders.csv',
                         chunksize=50000,
                         dtype=dtype_map,
                         parse_dates=['order_date']):
    print(chunk.dtypes)
    break

Nur benötigte Spalten auswählen

Verwenden Sie den Parameter usecols, um nur die Spalten zu laden, die Ihre Analyse benötigt. Wenn eine CSV-Datei 50 Spalten enthält, Ihre Aggregation aber nur 3 verwendet, gibt es keinen Grund, die übrigen 47 zu parsen. Die Kombination aus usecols und chunksize reduziert sowohl die Ein-/Ausgabezeit als auch den Speicherbedarf erheblich. Dies ist eine der einfachsten und wirkungsvollsten Optimierungen bei der Verarbeitung großer CSV-Dateien.

import pandas as pd

# Only read the three columns we actually need
for chunk in pd.read_csv(
    'large_transactions.csv',
    chunksize=100000,
    usecols=['date', 'amount', 'region']
):
    print(chunk.columns.tolist())
    print(chunk.memory_usage(deep=True).sum() / 1e6, 'MB per chunk')
    break

GroupBy-Aggregation in Blöcken

Eine groupby-Aggregation über mehrere Blöcke hinweg erfordert das Sammeln von Teilergebnissen. Berechnen Sie die groupby-Aggregation innerhalb jedes Blocks und kombinieren Sie die Ergebnisse anschließend mit einer zweiten groupby-Aggregation auf den verketteten Teilergebnissen. Um beispielsweise den Gesamtumsatz pro Region aus einer 10-GB-Datei zu ermitteln, sammeln Sie die Regionssummen pro Block in einer Liste, verketten diese und gruppieren sie erneut. Dieses zweistufige Aggregationsmuster wird manchmal als Map-Reduce-Ansatz bezeichnet.

import pandas as pd

partials = []
for chunk in pd.read_csv('sales.csv',
                         chunksize=100000,
                         usecols=['region', 'revenue']):
    partial = chunk.groupby('region')['revenue'].sum()
    partials.append(partial)

# Combine partial sums
final = pd.concat(partials).groupby(level=0).sum()
print('Revenue by region:')
print(final.sort_values(ascending=False))

Parse-Fehler über mehrere Blöcke hinweg behandeln

Große CSV-Dateien aus externen Quellen enthalten häufig fehlerhafte Zeilen — etwa zusätzliche Kommas, eine falsche Kodierung oder abgeschnittene Zeilen. Verwenden Sie on_bad_lines='skip' (Pandas 1.3+) oder error_bad_lines=False (ältere Pandas-Versionen), um fehlerhafte Zeilen stillschweigend zu überspringen, und encoding='latin-1', wenn das Parsen mit UTF-8 fehlschlägt. Erfassen Sie mit einem try-except-Block um die Verarbeitung jedes Blocks, bei welchen Blöcken Fehler aufgetreten sind. So entsteht eine robuste Pipeline, die bei einer einzelnen fehlerhaften Zeile in einer Datei mit 10 Millionen Zeilen nicht abstürzt.

import pandas as pd

bad_chunks = []
all_chunks = []

for i, chunk in enumerate(pd.read_csv(
    'raw_data.csv',
    chunksize=50000,
    on_bad_lines='skip',
    encoding='utf-8',
    encoding_errors='replace'
)):
    try:
        # Your transformation here
        all_chunks.append(chunk)
    except Exception as e:
        bad_chunks.append((i, str(e)))
        print(f'Chunk {i} error: {e}')

print(f'Processed {len(all_chunks)} chunks, {len(bad_chunks)} errors')

Ausgabedateien blockweise schreiben

Wenn auch Ihre verarbeiteten Ausgabedaten umfangreich sind, schreiben Sie die Ergebnisse inkrementell, statt alles im Arbeitsspeicher zu sammeln und am Ende zu schreiben. Öffnen Sie eine CSV-Datei und hängen Sie jeden verarbeiteten Block mit mode='a' und für nachfolgende Blöcke mit header=False an. Dadurch bleibt der Speicherbedarf der Ausgabepipeline konstant, und Sie können Teilergebnisse prüfen, bevor der gesamte Lauf abgeschlossen ist.

import pandas as pd

first_chunk = True
for chunk in pd.read_csv('input.csv', chunksize=100000):
    # Transform
    processed = chunk[chunk['status'] == 'active'].copy()
    processed['revenue_usd'] = processed['revenue'] * 1.10

    # Write incrementally
    mode = 'w' if first_chunk else 'a'
    processed.to_csv('output.csv',
                     mode=mode,
                     header=first_chunk,
                     index=False)
    first_chunk = False

print('Done writing output.csv')

Optimale Blockgröße schätzen

Die Wahl von chunksize ist ein Kompromiss: Ist der Wert zu klein, gibt es viele Python-Schleifendurchläufe und einen hohen Overhead; ist er zu groß, passen die Blöcke nicht in den Arbeitsspeicher. Ein praktikabler Ansatz besteht darin, einen Block zu laden, seinen Speicherbedarf mit chunk.memory_usage(deep=True).sum() zu messen und chunksize so festzulegen, dass jeder Block ungefähr 10–20 % des verfügbaren Arbeitsspeichers belegt. psutil.virtual_memory().available von Python liefert den zur Laufzeit verfügbaren Arbeitsspeicher und ermöglicht eine adaptive Berechnung von chunksize.

import pandas as pd

# Sample 1000 rows to estimate per-row memory
sample = pd.read_csv('big_file.csv', nrows=1000)
bytes_per_row = sample.memory_usage(deep=True).sum() / 1000
print(f'Bytes per row: {bytes_per_row:.0f}')

# Target: use at most 500 MB per chunk
target_bytes = 500 * 1024 * 1024
optimal_chunksize = int(target_bytes / bytes_per_row)
print(f'Recommended chunksize: {optimal_chunksize:,}')

Blockergebnisse effizient kombinieren

Wenn Sie viele DataFrames aus Blöcken in einer Liste sammeln und anschließend verketten, beachten Sie, dass der Aufruf von pd.concat für Hunderte kleiner DataFrames aufgrund wiederholter Speicherzuweisungen langsam ist. Ein besseres Muster besteht darin, innerhalb jedes Blocks zu aggregieren und nur das kleine aggregierte Ergebnis statt des vollständigen Blocks zu speichern. Wenn Sie tatsächlich alle Zeilen benötigen, ist das inkrementelle Schreiben in eine Parquet-Datei (mit pyarrow) schneller als ein abschließendes pd.concat.

import pandas as pd

# Efficient: aggregate first, small list of scalars
running_total = 0
running_count = 0

for chunk in pd.read_csv('sales.csv', chunksize=100000):
    running_total += chunk['amount'].sum()
    running_count += chunk['amount'].count()

print(f'Mean amount: {running_total / running_count:.2f}')

# Avoid: accumulating full chunk DataFrames
# results = []
# for chunk in reader:
#     results.append(chunk)   # memory grows to full file size
# df = pd.concat(results)     # slow for hundreds of chunks

Kurzer Test

Testen Sie Ihr Verständnis der Data-Analysis-Konzepte aus dieser Lektion.

Zusammenfassung der Lektion

In dieser Lektion haben Sie gelernt: chunksize in pd.read_csv gibt einen Iterator von DataFrames zurück und ermöglicht dadurch die speichereffiziente Verarbeitung großer Dateien; die Argumente usecols und dtype reduzieren den Speicherbedarf pro Block und beschleunigen das Parsen; und laufende Akkumulatoren (Summe, Anzahl, Teilergebnisse) vermeiden den Aufbau einer Liste mit allen Blöcken. Als Nächstes sehen wir uns Muster für die inkrementelle Aggregation über mehrere Blöcke hinweg genauer an.

Häufig gestellte Fragen

Ist die Lektion „CSV-Streaming mit chunksize“ kostenlos?

Ja — der vollständige Text von „CSV-Streaming mit chunksize“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Pandas & NumPy Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Pandas & NumPy Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „CSV-Streaming mit chunksize“?

Lesen Sie eine große CSV-Datei mit pd.read_csv(chunksize=) in Blöcken fester Größe ein, verarbeiten Sie jeden Block und verketten oder akkumulieren Sie die Ergebnisse. Du übst Pandas & NumPy Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Pandas & NumPy Academy zu starten?

Keine Vorkenntnisse erforderlich. Pandas & NumPy Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.

Wie lange dauert die Lektion „CSV-Streaming mit chunksize“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Pandas & NumPy Academy-Lektion Code schreiben und ausführen?

Ja. Jede Pandas & NumPy Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. CSV-Streaming mit chunksize
  2. Inkrementelle Aggregation über Blöcke
  3. Einführung in Dask DataFrames
  4. Parquet: Schneller spaltenbasierter Speicher
← Zurück zu Pandas & NumPy Academy