Pandas & NumPy Academy · Lektion

Strömmande CSV med chunksize

Läs en stor CSV-fil i block med fast storlek med pd.read_csv(chunksize=), bearbeta varje block och sammanfoga eller ackumulera resultaten.

Lektion 1 av 413 steg

Strömmande CSV med chunksize är en gratis lektion i Pandas & NumPy Academy på CoddyKit. Detta är lektion 1 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Pandas & NumPy Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Pandas & NumPy Academy innehåller totalt 4 lektioner.

Problemet med stora CSV-filer

När en CSV-fil är större än det tillgängliga RAM-minnet — till exempel en loggfil på 50 GB på en dator med 16 GB minne — misslyckas anropet pd.read_csv('file.csv') med ett MemoryError, eller så börjar systemet använda växlingsminnet intensivt och blir oanvändbart långsamt. Lösningen är läsning i chunkar: i stället för att läsa in hela filen på en gång bearbetar ni den i delar av fast storlek och samlar resultaten utan att någonsin ha allt i minnet samtidigt.

Parametern chunksize i read_csv

Om ni skickar chunksize=N till pd.read_csv() returneras en TextFileReader-iterator i stället för en DataFrame. Varje iteration returnerar en DataFrame med högst N rader. Filen läses in lazily — inga data läses in förrän ni begär nästa chunk. Den här iteratorn kan användas i en for-loop eller skickas till pd.concat(). Välj ett chunksize som är tillräckligt stort för effektiv I/O (till exempel 10 000–100 000 rader), men tillräckligt litet för att utan problem få plats i minnet.

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

Bearbeta varje chunk separat

Det vanligaste mönstret är att utföra en transformering eller filtrering på varje chunk och samla resultaten i en lista som sedan konkateneras. Ni kan till exempel filtrera rader som matchar ett villkor, beräkna statistik per chunk eller bara välja de kolumner ni behöver. När ni arbetar med delmängder är det bara den aktuella chunken som tar upp minne, medan resten av filen förblir orörd. Efter loopen sammanfogar ett enda pd.concat(results) den slutliga DataFrame-objektet.

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

Samla aggregeringar över chunkar

Ibland behöver ni inte behålla några rader alls — ni behöver bara en löpande aggregering. Håll reda på en löpande summa, ett antal eller min/max över chunkarna utan att bygga upp en lista med DataFrame-objekt. Det här är det mest minneseffektiva mönstret, eftersom minnesanvändningen förblir konstant oavsett filstorlek. Beräkna den slutliga statistiken från era ackumulatorer när allt är klart.

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

Ange dtype för snabbare chunkbaserad läsning

Som standard härleder Pandas kolumnernas datatyper från data, vilket kräver att varje chunk genomsöks två gånger (en gång för att härleda typen och en gång för att tolka data). Om ni anger argumentet dtype undviker ni denna extrakostnad och förhindrar dessutom inkonsekventa datatyper mellan chunkar. En kolumn som till exempel huvudsakligen innehåller heltal men har en tom cell kan härledas som float64 i en chunk och object i en annan. Genom att uttryckligen ange datatyper säkerställer ni konsekvent och snabbare läsning av alla chunkar.

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

Välj endast nödvändiga kolumner

Använd parametern usecols för att bara läsa in de kolumner som analysen behöver. Om en CSV-fil har 50 kolumner men er aggregering bara använder 3 finns det ingen anledning att tolka de övriga 47. Om ni kombinerar usecols med chunksize minskar ni både I/O-tiden och minnesanvändningen avsevärt. Det här är en av de enklaste och mest effektiva optimeringarna vid bearbetning av stora CSV-filer.

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-aggregering i chunkar

För att utföra en groupby-aggregering över chunkar måste ni samla delresultat. Beräkna groupby inom varje chunk och kombinera sedan resultaten med en andra groupby på de konkatenerade delresultaten. Om ni till exempel vill få fram den totala försäljningen per region i en fil på 10 GB samlar ni regionsummorna från varje chunk i en lista och konkatenerar dem, för att sedan gruppera igen. Det här mönstret med aggregering i två steg kallas ibland för ett map-reduce-tillvägagångssätt.

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

Hantera tolkningsfel över chunkar

Stora CSV-filer från externa källor innehåller ofta felaktigt formaterade rader — extra kommatecken, fel kodning eller avkortade rader. Använd on_bad_lines='skip' (Pandas 1.3+) eller error_bad_lines=False (äldre Pandas) för att tyst hoppa över felaktiga rader, och encoding='latin-1' om tolkningen med UTF-8 misslyckas. Håll reda på vilka chunkar som gav fel genom att använda try-except runt bearbetningen av varje chunk. På så sätt kan ni bygga en robust pipeline som inte kraschar på grund av en enda felaktig rad i en fil med 10 miljoner rader.

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')

Skriv utdatafiler chunkvis

När den bearbetade utdatan också är stor bör ni skriva resultaten stegvis i stället för att samla allt i minnet och skriva i slutet. Öppna en CSV-fil och lägg till varje bearbetad chunk med mode='a' och header=False för efterföljande chunkar. Då förblir minnesanvändningen i utdatapipelinen konstant, och ni kan granska delresultat innan hela körningen är klar.

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')

Uppskatta optimal chunkstorlek

Att välja chunksize är en avvägning: ett för litet värde innebär många iterationer i Python-loopen och hög omkostnad, medan ett för stort värde innebär att chunkarna inte får plats i RAM-minnet. Ett praktiskt tillvägagångssätt är att läsa in en chunk, mäta dess minnesanvändning med chunk.memory_usage(deep=True).sum() och ange chunksize så att varje chunk använder ungefär 10–20 % av det tillgängliga RAM-minnet. Pythons psutil.virtual_memory().available ger tillgängligt RAM under körning, vilket möjliggör en adaptiv beräkning av 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:,}')

Kombinera chunkresultat effektivt

När ni samlar många DataFrame-objekt från chunkar i en lista och sedan konkatenerar dem bör ni tänka på att anrop av pd.concat för hundratals små DataFrame-objekt är långsamt på grund av upprepade minnesallokeringar. Ett bättre mönster är att aggregera inom varje chunk och bara spara det lilla aggregerade resultatet, inte hela chunken. Om ni verkligen behöver alla rader går det snabbare att skriva stegvis till en Parquet-fil (med pyarrow) än att använda pd.concat i slutet.

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

Snabbtest

Testa era kunskaper om dataanalys från den här lektionen.

Sammanfattning av lektionen

I den här lektionen har ni lärt er att chunksize i pd.read_csv returnerar en iterator med DataFrame-objekt som möjliggör minneseffektiv bearbetning av stora filer, att argumenten usecols och dtype minskar minnesanvändningen per chunk och snabbar upp tolkningen, samt att löpande ackumulatorer (summa, antal och delresultat) förhindrar att en lista med alla chunkar byggs upp. Nästa steg är att titta närmare på mönster för stegvis aggregering över chunkar.

Gratis att börja

Lär dig Python med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
30
Lektioner
120

Vanliga frågor

Är lektionen ”Strömmande CSV med chunksize” gratis?

Ja – hela texten till ”Strömmande CSV med chunksize” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Pandas & NumPy Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i Pandas & NumPy Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Strömmande CSV med chunksize”?

Läs en stor CSV-fil i block med fast storlek med pd.read_csv(chunksize=), bearbeta varje block och sammanfoga eller ackumulera resultaten. Ni övar på Pandas & NumPy Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Pandas & NumPy Academy?

Du behöver inga förkunskaper. Utbildningen i Pandas & NumPy Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.

Hur lång tid tar lektionen ”Strömmande CSV med chunksize”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Pandas & NumPy Academy-lektionen?

Ja. Varje Pandas & NumPy Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Strömmande CSV med chunksize
  2. Inkrementell aggregering över block
  3. Introduktion till Dask DataFrames
  4. Parquet: snabb kolumnlagring
← Tillbaka till Pandas & NumPy Academy