Einführung
Die Verarbeitung großer CSV-Dateien ist eine häufige Herausforderung für Python-Entwickler. Dieses Tutorial führt Sie durch effiziente Techniken zur effektiven Verarbeitung dieser Dateien und konzentriert sich dabei auf die Optimierung der Leistung und des Speicherverbrauchs. Am Ende dieses Labs verfügen Sie über praktisches Wissen, um datenintensive CSV-Verarbeitungsaufgaben in Python zu bewältigen.
Unabhängig davon, ob Sie Kundendaten analysieren, Finanzunterlagen verarbeiten oder mit einer anderen Art von strukturierten Daten arbeiten, helfen Ihnen die in diesem Lab erlernten Fähigkeiten, große Datensätze effizient zu verarbeiten, ohne auf Speicherprobleme zu stoßen.
Erstellen und Lesen einer einfachen CSV-Datei
CSV (Comma-Separated Values) ist ein beliebtes Dateiformat zur Speicherung tabellarischer Daten. In diesem Schritt erstellen wir eine einfache CSV-Datei und lernen, wie man sie mit dem in Python integrierten csv-Modul liest.
CSV-Dateien verstehen
Eine CSV-Datei speichert Daten in einem Nur-Text-Format, wobei:
- Jede Zeile eine Datenzeile darstellt
- Werte innerhalb jeder Zeile durch ein Trennzeichen (typischerweise ein Komma) getrennt sind
- Die erste Zeile oft Spaltenüberschriften enthält
Beginnen wir mit der Erstellung einer einfachen CSV-Datei, mit der wir arbeiten können.
Erstellen einer CSV-Datei
Erstellen wir zunächst ein Verzeichnis, in dem wir arbeiten, und erstellen Sie dann eine einfache CSV-Datei:
- Öffnen Sie das Terminal in der WebIDE
- Erstellen Sie im Editor eine neue Python-Datei mit dem Namen
csv_basics.py
Fügen Sie nun den folgenden Code zu csv_basics.py hinzu:
import csv
## Data to write to CSV
data = [
['Name', 'Age', 'City'], ## Header row
['John Smith', '28', 'New York'],
['Sarah Johnson', '32', 'San Francisco'],
['Michael Brown', '45', 'Chicago'],
['Emily Davis', '36', 'Boston'],
['David Wilson', '52', 'Seattle']
]
## Writing data to a CSV file
with open('sample_data.csv', 'w', newline='') as file:
writer = csv.writer(file)
writer.writerows(data)
print("CSV file 'sample_data.csv' created successfully.")
Führen Sie diesen Code aus, indem Sie den folgenden Befehl im Terminal ausführen:
python3 csv_basics.py
Erwartete Ausgabe:
CSV file 'sample_data.csv' created successfully.
Dadurch wird im aktuellen Verzeichnis eine neue CSV-Datei mit dem Namen sample_data.csv erstellt. Sie können den Inhalt dieser Datei anzeigen, indem Sie Folgendes ausführen:
cat sample_data.csv
Erwartete Ausgabe:
Name,Age,City
John Smith,28,New York
Sarah Johnson,32,San Francisco
Michael Brown,45,Chicago
Emily Davis,36,Boston
David Wilson,52,Seattle
Lesen einer CSV-Datei
Lesen wir nun die CSV-Datei, die wir gerade erstellt haben. Erstellen Sie eine neue Datei mit dem Namen read_csv.py mit dem folgenden Code:
import csv
## Reading a CSV file
with open('sample_data.csv', 'r') as file:
reader = csv.reader(file)
print("Contents of sample_data.csv:")
print("--------------------------")
for row in reader:
print(row)
## Reading and accessing specific columns
print("\nReading specific columns:")
print("--------------------------")
with open('sample_data.csv', 'r') as file:
reader = csv.reader(file)
headers = next(reader) ## Skip the header row
for row in reader:
name = row[0]
age = row[1]
city = row[2]
print(f"Name: {name}, Age: {age}, City: {city}")
Führen Sie diesen Code mit Folgendem aus:
python3 read_csv.py
Erwartete Ausgabe:
Contents of sample_data.csv:
--------------------------
['Name', 'Age', 'City']
['John Smith', '28', 'New York']
['Sarah Johnson', '32', 'San Francisco']
['Michael Brown', '45', 'Chicago']
['Emily Davis', '36', 'Boston']
['David Wilson', '52', 'Seattle']
Reading specific columns:
--------------------------
Name: John Smith, Age: 28, City: New York
Name: Sarah Johnson, Age: 32, City: San Francisco
Name: Michael Brown, Age: 45, City: Chicago
Name: Emily Davis, Age: 36, City: Boston
Name: David Wilson, Age: 52, City: Seattle
Das CSV-Modul verstehen
Das Python csv-Modul stellt zwei Hauptklassen bereit:
csv.reader: Liest CSV-Dateien und gibt jede Zeile als Liste von Strings zurückcsv.writer: Schreibt Daten in CSV-Dateien
Dieses Modul behandelt alle Komplexitäten im Umgang mit verschiedenen CSV-Formaten, wie z. B. das Escapen von Sonderzeichen und die Behandlung von Anführungszeichen.
In diesem Schritt haben Sie gelernt, wie man eine einfache CSV-Datei erstellt und liest. Im nächsten Schritt werden wir effizientere Möglichkeiten zur Verarbeitung größerer CSV-Dateien untersuchen.
Verwendung von DictReader für die komfortable CSV-Verarbeitung
Im vorherigen Schritt haben wir mit den grundlegenden Funktionen csv.reader und csv.writer gearbeitet. Lassen Sie uns nun eine bequemere Methode zur Verarbeitung von CSV-Dateien mit der Klasse csv.DictReader untersuchen, die besonders nützlich ist, wenn Sie mit Daten arbeiten, die Spaltenüberschriften haben.
Was ist DictReader?
csv.DictReader liest CSV-Dateien und gibt jede Zeile als Dictionary zurück, wobei:
- Die Schlüssel aus den Spaltenüberschriften (standardmäßig die erste Zeile der CSV-Datei) entnommen werden
- Die Werte die entsprechenden Daten aus jeder Zeile sind
Dieser Ansatz macht Ihren Code lesbarer und weniger fehleranfällig, da Sie auf Spalten nach Namen anstatt nach Index verweisen können.
Erstellen einer größeren Testdatei
Erstellen wir zunächst eine etwas größere CSV-Datei, um die Vorteile von DictReader zu demonstrieren. Erstellen Sie eine neue Datei mit dem Namen create_users_data.py mit dem folgenden Code:
import csv
import random
## Generate some sample user data
def generate_users(count):
users = [['id', 'name', 'email', 'age', 'country']] ## Header row
domains = ['gmail.com', 'yahoo.com', 'outlook.com', 'example.com']
countries = ['USA', 'Canada', 'UK', 'Australia', 'Germany', 'France', 'Japan', 'Brazil']
first_names = ['John', 'Jane', 'Michael', 'Emily', 'David', 'Sarah', 'Robert', 'Lisa']
last_names = ['Smith', 'Johnson', 'Brown', 'Davis', 'Wilson', 'Miller', 'Jones', 'Taylor']
for i in range(1, count + 1):
first_name = random.choice(first_names)
last_name = random.choice(last_names)
name = f"{first_name} {last_name}"
email = f"{first_name.lower()}.{last_name.lower()}@{random.choice(domains)}"
age = random.randint(18, 65)
country = random.choice(countries)
users.append([str(i), name, email, str(age), country])
return users
## Create a CSV file with 100 users
users_data = generate_users(100)
## Write data to CSV file
with open('users_data.csv', 'w', newline='') as file:
writer = csv.writer(file)
writer.writerows(users_data)
print(f"Created 'users_data.csv' with 100 user records")
Führen Sie das Skript aus, um die Datei zu erstellen:
python3 create_users_data.py
Erwartete Ausgabe:
Created 'users_data.csv' with 100 user records
Untersuchen wir die ersten Zeilen dieser neuen Datei:
head -n 5 users_data.csv
Sie sollten die Header-Zeile gefolgt von 4 Datenzeilen sehen:
id,name,email,age,country
1,John Smith,john.smith@gmail.com,25,USA
2,Emily Brown,emily.brown@yahoo.com,32,Canada
3,David Jones,david.jones@outlook.com,45,UK
4,Sarah Wilson,sarah.wilson@example.com,28,Australia
Verwenden von DictReader zur Verarbeitung der CSV-Datei
Erstellen wir nun ein Skript, um diese Datei mit DictReader zu verarbeiten. Erstellen Sie eine neue Datei mit dem Namen dict_reader_example.py mit dem folgenden Code:
import csv
## Read the CSV file using DictReader
with open('users_data.csv', 'r') as file:
csv_reader = csv.DictReader(file)
## Print the field names (column headers)
print(f"Column headers: {csv_reader.fieldnames}")
print("\nFirst 5 records:")
print("-----------------")
## Print the first 5 records
for i, row in enumerate(csv_reader):
if i < 5:
## Access fields by name
print(f"User {row['id']}: {row['name']}, {row['age']} years old, from {row['country']}")
print(f" Email: {row['email']}")
else:
break
## Using DictReader for data analysis
with open('users_data.csv', 'r') as file:
csv_reader = csv.DictReader(file)
## Calculate average age
total_age = 0
user_count = 0
## Count users by country
countries = {}
for row in csv_reader:
user_count += 1
total_age += int(row['age'])
## Count users by country
country = row['country']
if country in countries:
countries[country] += 1
else:
countries[country] = 1
avg_age = total_age / user_count if user_count > 0 else 0
print("\nData Analysis:")
print("--------------")
print(f"Total users: {user_count}")
print(f"Average age: {avg_age:.2f} years")
print("\nUsers by country:")
for country, count in sorted(countries.items(), key=lambda x: x[1], reverse=True):
print(f" {country}: {count} users")
Führen Sie dieses Skript aus:
python3 dict_reader_example.py
Erwartete Ausgabe (Ihre genauen Werte können variieren, da die Daten zufällig generiert werden):
Column headers: ['id', 'name', 'email', 'age', 'country']
First 5 records:
-----------------
User 1: John Smith, 25 years old, from USA
Email: john.smith@gmail.com
User 2: Emily Brown, 32 years old, from Canada
Email: emily.brown@yahoo.com
User 3: David Jones, 45 years old, from UK
Email: david.jones@outlook.com
User 4: Sarah Wilson, 28 years old, from Australia
Email: sarah.wilson@example.com
User 5: Michael Taylor, 37 years old, from Germany
Email: michael.taylor@example.com
Data Analysis:
--------------
Total users: 100
Average age: 41.35 years
Users by country:
USA: 16 users
Canada: 14 users
Japan: 13 users
UK: 12 users
Germany: 12 users
Australia: 12 users
France: 11 users
Brazil: 10 users
Vorteile der Verwendung von DictReader
Wie Sie sehen können, bietet die Verwendung von DictReader mehrere Vorteile:
- Lesbarer Code: Sie können auf Felder nach Namen zugreifen, anstatt sich Indexpositionen zu merken
- Selbstdokumentierend: Der Code zeigt deutlich, auf welches Feld Sie zugreifen
- Flexibilität: Wenn sich die Spaltenreihenfolge in der CSV-Datei ändert, funktioniert Ihr Code weiterhin, solange die Spaltennamen gleich bleiben
Dieser Ansatz ist besonders nützlich, wenn Sie mit realen Daten arbeiten, die viele Spalten haben, oder wenn sich die Spaltenreihenfolge im Laufe der Zeit ändern kann.
Im nächsten Schritt werden wir effiziente Techniken zur Verarbeitung größerer CSV-Dateien untersuchen, ohne alles auf einmal in den Speicher zu laden.
Effizientes Verarbeiten großer CSV-Dateien
In realweltlichen Szenarien müssen Sie möglicherweise CSV-Dateien verarbeiten, die mehrere Gigabyte groß sind. Das vollständige Laden solcher Dateien in den Speicher kann dazu führen, dass Ihre Anwendung abstürzt oder sich erheblich verlangsamt. In diesem Schritt werden wir Techniken zur effizienten Verarbeitung großer CSV-Dateien untersuchen.
Die Speicherherausforderung bei großen Dateien
Bei der Arbeit mit CSV-Dateien gibt es drei gängige Ansätze, die jeweils unterschiedliche Speicheranforderungen haben:
- Laden der gesamten Datei in den Speicher - Einfach, aber verbraucht den meisten Speicher
- Streamen der Datei Zeile für Zeile - Verbraucht minimalen Speicher, kann aber für komplexe Operationen langsamer sein
- Chunking (Aufteilen in Blöcke) - Ein Mittelweg, der die Datei in handhabbaren Blöcken verarbeitet
Lassen Sie uns jeden dieser Ansätze anhand praktischer Beispiele untersuchen.
Erstellen einer größeren Beispieldatei
Erstellen wir zunächst eine größere Beispieldatei, um diese Techniken zu demonstrieren. Erstellen Sie eine neue Datei mit dem Namen create_large_csv.py:
import csv
import random
from datetime import datetime, timedelta
def create_large_csv(filename, num_rows):
## Define column headers
headers = ['transaction_id', 'date', 'customer_id', 'product_id', 'amount', 'status']
## Create a file with the specified number of rows
with open(filename, 'w', newline='') as file:
writer = csv.writer(file)
writer.writerow(headers)
## Generate random data
start_date = datetime(2022, 1, 1)
status_options = ['completed', 'pending', 'failed', 'refunded']
for i in range(1, num_rows + 1):
## Generate random values
transaction_id = f"TXN-{i:08d}"
days_offset = random.randint(0, 365)
date = (start_date + timedelta(days=days_offset)).strftime('%Y-%m-%d')
customer_id = f"CUST-{random.randint(1001, 9999)}"
product_id = f"PROD-{random.randint(101, 999)}"
amount = round(random.uniform(10.0, 500.0), 2)
status = random.choice(status_options)
## Write row to CSV
writer.writerow([transaction_id, date, customer_id, product_id, amount, status])
## Print progress indicator for every 10,000 rows
if i % 10000 == 0:
print(f"Generated {i} rows...")
## Create a CSV file with 50,000 rows (about 5-10 MB)
create_large_csv('transactions.csv', 50000)
print("Large CSV file 'transactions.csv' has been created.")
Führen Sie dieses Skript aus, um die Datei zu erstellen:
python3 create_large_csv.py
Erwartete Ausgabe:
Generated 10000 rows...
Generated 20000 rows...
Generated 30000 rows...
Generated 40000 rows...
Generated 50000 rows...
Large CSV file 'transactions.csv' has been created.
Sie können die Größe der Datei mit folgendem Befehl überprüfen:
ls -lh transactions.csv
Erwartete Ausgabe (die Größe kann leicht variieren):
-rw-r--r-- 1 labex labex 3.8M Apr 15 12:30 transactions.csv
Ansatz 1: Zeilenweise Verarbeitung (Streaming)
Der speichereffizienteste Ansatz ist die zeilenweise Verarbeitung einer CSV-Datei. Erstellen Sie eine Datei mit dem Namen streaming_example.py:
import csv
import time
def process_csv_streaming(filename):
print(f"Processing {filename} using streaming (line by line)...")
start_time = time.time()
## Track some statistics
row_count = 0
total_amount = 0
status_counts = {'completed': 0, 'pending': 0, 'failed': 0, 'refunded': 0}
## Process the file line by line
with open(filename, 'r') as file:
reader = csv.DictReader(file)
for row in reader:
## Increment row counter
row_count += 1
## Process row data
amount = float(row['amount'])
status = row['status']
## Update statistics
total_amount += amount
status_counts[status] += 1
## Calculate and display results
end_time = time.time()
processing_time = end_time - start_time
print(f"\nResults:")
print(f"Processed {row_count:,} rows in {processing_time:.2f} seconds")
print(f"Total transaction amount: ${total_amount:,.2f}")
print(f"Average transaction amount: ${total_amount/row_count:.2f}")
print("\nTransaction status breakdown:")
for status, count in status_counts.items():
percentage = (count / row_count) * 100
print(f" {status}: {count:,} ({percentage:.1f}%)")
## Process the file
process_csv_streaming('transactions.csv')
Führen Sie dieses Skript aus:
python3 streaming_example.py
Erwartete Ausgabe (Ihre genauen Zahlen können variieren):
Processing transactions.csv using streaming (line by line)...
Results:
Processed 50,000 rows in 0.17 seconds
Total transaction amount: $12,739,853.35
Average transaction amount: $254.80
Transaction status breakdown:
completed: 12,432 (24.9%)
pending: 12,598 (25.2%)
failed: 12,414 (24.8%)
refunded: 12,556 (25.1%)
Ansatz 2: Chunked Processing (Blockweise Verarbeitung)
Für komplexere Operationen oder wenn Sie Daten in Batches verarbeiten müssen, können Sie einen Chunked-Ansatz verwenden. Erstellen Sie eine Datei mit dem Namen chunked_example.py:
import csv
import time
def process_csv_chunked(filename, chunk_size=10000):
print(f"Processing {filename} using chunks of {chunk_size} rows...")
start_time = time.time()
## Track some statistics
row_count = 0
total_amount = 0
status_counts = {'completed': 0, 'pending': 0, 'failed': 0, 'refunded': 0}
## Process the file in chunks
with open(filename, 'r') as file:
reader = csv.DictReader(file)
chunk = []
for row in reader:
## Add row to current chunk
chunk.append(row)
## When chunk reaches desired size, process it
if len(chunk) >= chunk_size:
## Process the chunk
for row_data in chunk:
## Update statistics
row_count += 1
amount = float(row_data['amount'])
status = row_data['status']
total_amount += amount
status_counts[status] += 1
print(f"Processed chunk of {len(chunk)} rows... ({row_count:,} total)")
## Clear the chunk for next batch
chunk = []
## Process any remaining rows in the last chunk
if chunk:
for row_data in chunk:
row_count += 1
amount = float(row_data['amount'])
status = row_data['status']
total_amount += amount
status_counts[status] += 1
print(f"Processed final chunk of {len(chunk)} rows... ({row_count:,} total)")
## Calculate and display results
end_time = time.time()
processing_time = end_time - start_time
print(f"\nResults:")
print(f"Processed {row_count:,} rows in {processing_time:.2f} seconds")
print(f"Total transaction amount: ${total_amount:,.2f}")
print(f"Average transaction amount: ${total_amount/row_count:.2f}")
print("\nTransaction status breakdown:")
for status, count in status_counts.items():
percentage = (count / row_count) * 100
print(f" {status}: {count:,} ({percentage:.1f}%)")
## Process the file with chunks of 10,000 rows
process_csv_chunked('transactions.csv', chunk_size=10000)
Führen Sie dieses Skript aus:
python3 chunked_example.py
Erwartete Ausgabe:
Processing transactions.csv using chunks of 10000 rows...
Processed chunk of 10000 rows... (10,000 total)
Processed chunk of 10000 rows... (20,000 total)
Processed chunk of 10000 rows... (30,000 total)
Processed chunk of 10000 rows... (40,000 total)
Processed chunk of 10000 rows... (50,000 total)
Results:
Processed 50,000 rows in 0.20 seconds
Total transaction amount: $12,739,853.35
Average transaction amount: $254.80
Transaction status breakdown:
completed: 12,432 (24.9%)
pending: 12,598 (25.2%)
failed: 12,414 (24.8%)
refunded: 12,556 (25.1%)
Speichervergleich
Die wesentlichen Unterschiede zwischen diesen Ansätzen sind:
Streaming (Zeile für Zeile):
- Verwendet unabhängig von der Dateigröße minimalen Speicher
- Am besten für sehr große Dateien geeignet
- Einfache Operationen für jede Zeile
Chunked Processing (Blockweise Verarbeitung):
- Verwendet mehr Speicher als Streaming, ist aber immer noch effizient
- Gut für Operationen, die Zeilen in Batches verarbeiten müssen
- Bietet Fortschrittsaktualisierungen während der Verarbeitung
- Kann für die parallele Verarbeitung mit Multiprocessing kombiniert werden
Für die meisten praktischen Zwecke wird der Streaming-Ansatz empfohlen, es sei denn, Sie benötigen explizit Batch-Verarbeitungsfunktionen. Er bietet die beste Speichereffizienz bei gleichzeitig guter Leistung.
Im nächsten Schritt werden wir die Verwendung von Bibliotheken von Drittanbietern wie Pandas für noch leistungsfähigere CSV-Verarbeitungsfunktionen untersuchen.
Verwendung von Pandas für die erweiterte CSV-Verarbeitung
Während das eingebaute csv-Modul von Python leistungsstark ist, bietet die pandas-Bibliothek erweiterte Funktionen für Datenanalyse und -manipulation. In diesem Schritt werden wir untersuchen, wie man Pandas für die effiziente CSV-Verarbeitung verwendet.
Installieren von Pandas
Installieren wir zunächst die Pandas-Bibliothek:
pip install pandas
Erwartete Ausgabe:
Collecting pandas
Downloading pandas-2.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.3 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 12.3/12.3 MB 42.6 MB/s eta 0:00:00
...
Successfully installed pandas-2.0.0 numpy-1.24.3 python-dateutil-2.8.2 pytz-2023.3 tzdata-2023.3
Lesen von CSV-Dateien mit Pandas
Pandas macht es einfach, CSV-Daten zu lesen, zu analysieren und zu manipulieren. Erstellen Sie eine Datei mit dem Namen pandas_basic.py:
import pandas as pd
import time
def process_with_pandas(filename):
print(f"Processing {filename} with pandas...")
start_time = time.time()
## Read the CSV file into a DataFrame
df = pd.read_csv(filename)
## Display basic information
print(f"\nDataFrame Info:")
print(f"Shape: {df.shape} (rows, columns)")
print(f"Column names: {', '.join(df.columns)}")
## Display the first 5 rows
print("\nFirst 5 rows:")
print(df.head())
## Basic statistics
print("\nSummary statistics for numeric columns:")
print(df.describe())
## Group by analysis
print("\nTransaction counts by status:")
status_counts = df['status'].value_counts()
print(status_counts)
## Calculate average amount by status
print("\nAverage transaction amount by status:")
avg_by_status = df.groupby('status')['amount'].mean()
print(avg_by_status)
## Calculate total amount by date (first 5 dates)
print("\nTotal transaction amount by date (first 5 dates):")
total_by_date = df.groupby('date')['amount'].sum().sort_values(ascending=False).head(5)
print(total_by_date)
end_time = time.time()
print(f"\nProcessed in {end_time - start_time:.2f} seconds")
## Process the transactions file
process_with_pandas('transactions.csv')
Führen Sie dieses Skript aus:
python3 pandas_basic.py
Erwartete Ausgabe (gekürzt für die Kürze):
Processing transactions.csv with pandas...
DataFrame Info:
Shape: (50000, 6) (rows, columns)
Column names: transaction_id, date, customer_id, product_id, amount, status
First 5 rows:
transaction_id date customer_id product_id amount status
0 TXN-00000001 2022-12-19 CUST-5421 PROD-383 385.75 refunded
1 TXN-00000002 2022-02-01 CUST-7078 PROD-442 286.83 completed
2 TXN-00000003 2022-12-24 CUST-2356 PROD-701 364.87 failed
3 TXN-00000004 2022-04-09 CUST-3458 PROD-854 247.73 pending
4 TXN-00000005 2022-03-07 CUST-6977 PROD-307 298.69 completed
Summary statistics for numeric columns:
amount
count 50000.000000
mean 254.797067
std 141.389125
min 10.010000
25% 127.732500
50% 254.865000
75% 381.387500
max 499.990000
Transaction counts by status:
pending 12598
refunded 12556
completed 12432
failed 12414
Name: status, dtype: int64
Average transaction amount by status:
status
completed 255.028733
failed 254.709444
pending 254.690785
refunded 254.760390
Name: amount, dtype: float64
Total transaction amount by date (first 5 dates):
date
2022-01-20 38883.19
2022-08-30 38542.49
2022-03-10 38331.67
2022-11-29 38103.61
2022-06-24 37954.87
Name: amount, dtype: float64
Processed in 0.11 seconds
Verarbeitung großer CSV-Dateien mit Pandas
Obwohl Pandas leistungsstark ist, kann es beim Laden großer CSV-Dateien viel Speicher verbrauchen. Für sehr große Dateien können Sie den Parameter chunksize verwenden, um die Datei in Blöcken zu lesen. Erstellen Sie eine Datei mit dem Namen pandas_chunked.py:
import pandas as pd
import time
def process_large_csv_with_pandas(filename, chunk_size=10000):
print(f"Processing {filename} with pandas using chunks of {chunk_size} rows...")
start_time = time.time()
## Initialize variables to store aggregated results
total_rows = 0
total_amount = 0
status_counts = {'completed': 0, 'pending': 0, 'failed': 0, 'refunded': 0}
daily_totals = {}
## Process the file in chunks
for chunk_num, chunk in enumerate(pd.read_csv(filename, chunksize=chunk_size)):
## Update row count
chunk_rows = len(chunk)
total_rows += chunk_rows
## Update total amount
chunk_amount = chunk['amount'].sum()
total_amount += chunk_amount
## Update status counts
for status, count in chunk['status'].value_counts().items():
status_counts[status] += count
## Update daily totals
for date, group in chunk.groupby('date'):
if date in daily_totals:
daily_totals[date] += group['amount'].sum()
else:
daily_totals[date] = group['amount'].sum()
print(f"Processed chunk {chunk_num + 1} ({total_rows:,} rows so far)")
## Calculate results
end_time = time.time()
processing_time = end_time - start_time
print(f"\nResults after processing {total_rows:,} rows in {processing_time:.2f} seconds:")
print(f"Total transaction amount: ${total_amount:,.2f}")
print(f"Average transaction amount: ${total_amount/total_rows:.2f}")
print("\nTransaction status breakdown:")
for status, count in status_counts.items():
percentage = (count / total_rows) * 100
print(f" {status}: {count:,} ({percentage:.1f}%)")
## Show top 5 days by transaction amount
print("\nTop 5 days by transaction amount:")
top_days = sorted(daily_totals.items(), key=lambda x: x[1], reverse=True)[:5]
for date, amount in top_days:
print(f" {date}: ${amount:,.2f}")
## Process the transactions file with chunks
process_large_csv_with_pandas('transactions.csv', chunk_size=10000)
Führen Sie dieses Skript aus:
python3 pandas_chunked.py
Erwartete Ausgabe:
Processing transactions.csv with pandas using chunks of 10000 rows...
Processed chunk 1 (10,000 rows so far)
Processed chunk 2 (20,000 rows so far)
Processed chunk 3 (30,000 rows so far)
Processed chunk 4 (40,000 rows so far)
Processed chunk 5 (50,000 rows so far)
Results after processing 50,000 rows in 0.34 seconds:
Total transaction amount: $12,739,853.35
Average transaction amount: $254.80
Transaction status breakdown:
completed: 12,432 (24.9%)
pending: 12,598 (25.2%)
failed: 12,414 (24.8%)
refunded: 12,556 (25.1%)
Top 5 days by transaction amount:
2022-01-20: $38,883.19
2022-08-30: $38,542.49
2022-03-10: $38,331.67
2022-11-29: $38,103.61
2022-06-24: $37,954.87
Filtern und Transformieren von Daten mit Pandas
Einer der großen Vorteile von Pandas ist die Möglichkeit, Daten einfach zu filtern und zu transformieren. Erstellen Sie eine Datei mit dem Namen pandas_filter.py:
import pandas as pd
import time
def filter_and_transform(filename):
print(f"Filtering and transforming data from {filename}...")
start_time = time.time()
## Read the CSV file
df = pd.read_csv(filename)
## 1. Filter: Get only completed transactions
completed = df[df['status'] == 'completed']
print(f"Number of completed transactions: {len(completed)}")
## 2. Filter: Get high-value transactions (over $400)
high_value = df[df['amount'] > 400]
print(f"Number of high-value transactions (>${400}): {len(high_value)}")
## 3. Filter: Transactions from first quarter of 2022
df['date'] = pd.to_datetime(df['date']) ## Convert to datetime
q1_2022 = df[(df['date'] >= '2022-01-01') & (df['date'] <= '2022-03-31')]
print(f"Number of transactions in Q1 2022: {len(q1_2022)}")
## 4. Add a new column: transaction_month
df['month'] = df['date'].dt.strftime('%Y-%m')
## 5. Group by month and status
monthly_by_status = df.groupby(['month', 'status']).agg({
'transaction_id': 'count',
'amount': 'sum'
}).rename(columns={'transaction_id': 'count'})
## Calculate success rate by month (completed / total)
print("\nTransaction success rates by month:")
for month, month_data in df.groupby('month'):
total = len(month_data)
completed = len(month_data[month_data['status'] == 'completed'])
success_rate = (completed / total) * 100
print(f" {month}: {success_rate:.1f}% ({completed}/{total})")
## Save filtered data to a new CSV file
completed_high_value = df[(df['status'] == 'completed') & (df['amount'] > 300)]
output_file = 'high_value_completed.csv'
completed_high_value.to_csv(output_file, index=False)
end_time = time.time()
print(f"\nFiltering completed in {end_time - start_time:.2f} seconds")
print(f"Saved {len(completed_high_value)} high-value completed transactions to {output_file}")
## Filter and transform the data
filter_and_transform('transactions.csv')
Führen Sie dieses Skript aus:
python3 pandas_filter.py
Erwartete Ausgabe:
Filtering and transforming data from transactions.csv...
Number of completed transactions: 12432
Number of high-value transactions (>$400): 6190
Number of transactions in Q1 2022: 12348
Transaction success rates by month:
2022-01: 24.8% (1048/4225)
2022-02: 25.0% (1010/4034)
2022-03: 25.4% (1042/4089)
2022-04: 24.2% (978/4052)
2022-05: 24.4% (1047/4297)
2022-06: 24.4% (1046/4280)
2022-07: 24.7% (1071/4341)
2022-08: 25.1% (1090/4343)
2022-09: 26.1% (1091/4177)
2022-10: 24.1% (1008/4182)
2022-11: 24.8% (1009/4075)
2022-12: 25.2% (992/3905)
Filtering completed in 0.38 seconds
Saved 6304 high-value completed transactions to high_value_completed.csv
Vorteile der Verwendung von Pandas
Wie Sie an diesen Beispielen sehen können, bietet Pandas mehrere Vorteile für die CSV-Verarbeitung:
- Umfangreiche Funktionalität: Eingebaute Methoden zum Filtern, Gruppieren, Aggregieren und Transformieren von Daten
- Leistung: Optimierter C-Code im Hintergrund für schnelle Operationen auf großen Datensätzen
- Einfache Datenanalyse: Einfache Möglichkeiten zur Berechnung von Statistiken und zum Gewinnen von Erkenntnissen
- Visualisierungsmöglichkeiten: Einfache Integration mit Plotting-Bibliotheken (nicht in den Beispielen gezeigt)
- Chunked Processing (Blockweise Verarbeitung): Möglichkeit, Dateien zu verarbeiten, die größer als der verfügbare Speicher sind
Für die meisten Datenanalyseaufgaben mit CSV-Dateien ist Pandas der empfohlene Ansatz, es sei denn, Sie haben spezifische Speicherbeschränkungen, die die Verwendung des reinen Python csv-Moduls erfordern.
Zusammenfassung
In diesem Tutorial haben Sie verschiedene Ansätze zur effizienten Verarbeitung von CSV-Dateien in Python gelernt, von kleinen Datensätzen bis hin zu großen, die ein sorgfältiges Speichermanagement erfordern:
Grundlegende CSV-Verarbeitung: Verwendung des integrierten
csv-Moduls von Python zum Lesen und Schreiben von CSV-Dateien mitcsv.readerundcsv.writer.Wörterbuchbasierte Verarbeitung: Verwendung von
csv.DictReader, um mit CSV-Daten auf intuitivere Weise zu arbeiten und auf Felder nach Namen anstelle von Indizes zuzugreifen.Effiziente Verarbeitungstechniken:
- Streaming: Verarbeitung von Dateien Zeile für Zeile für minimalen Speicherverbrauch
- Chunking (Blockweise Verarbeitung): Verarbeitung von Dateien in Batches für ein besseres Speichermanagement
Erweiterte Verarbeitung mit Pandas:
- Lesen von CSV-Dateien in DataFrames
- Analysieren und Filtern von Daten
- Verarbeiten großer Dateien in Blöcken
- Transformieren und Exportieren von Daten
Diese Techniken bieten ein umfassendes Toolkit für die Verarbeitung von CSV-Dateien beliebiger Größe in Python. Für die meisten Datenanalyseaufgaben ist Pandas die empfohlene Bibliothek, da sie über eine umfangreiche Funktionalität und Leistung verfügt. Für sehr große Dateien oder einfache Verarbeitungsaufgaben können die Streaming- und Chunking-Ansätze mit dem integrierten csv-Modul jedoch speichereffizienter sein.
Durch die Anwendung der geeigneten Technik basierend auf Ihren spezifischen Anforderungen können Sie CSV-Dateien beliebiger Größe effizient verarbeiten, ohne auf Speicherprobleme zu stoßen.



