Erstellen Sie Ihren modernen Datenanalyse-Stack mit Python, Parquet und DuckDB
Bild vom Autor

# Einführung

Die Datenanalyse hat sich in den letzten Jahren verändert. Der traditionelle Ansatz, alles in eine relationale Datenbank zu laden und SQL-Abfragen auszuführen, funktioniert immer noch, ist aber für einige analytische Workloads oft übertrieben. Daten speichern in Parkett Dateien und deren direkte Abfrage mit DuckDB ist schneller, einfacher und effektiver.

In diesem Artikel zeige ich Ihnen, wie Sie einen Datenanalyse-Stack erstellen Python das DuckDB verwendet, um in Parquet-Dateien gespeicherte Daten abzufragen. Wir arbeiten mit einem Beispieldatensatz, untersuchen die Funktionsweise der einzelnen Komponenten und verstehen, warum dieser Ansatz für Ihre Information-Science-Projekte nützlich sein kann.

Den Code finden Sie auf GitHub.

# Voraussetzungen

Bevor wir beginnen, stellen Sie sicher, dass Sie Folgendes haben:

  • Python 3.10 oder eine neuere Model installiert
  • Ein Verständnis der SQL-Grundlagen und Pandas DataFrame-Operationen
  • Vertrautheit mit Datenanalysekonzepten

Installieren Sie außerdem die erforderlichen Bibliotheken:

pip set up duckdb pandas pyarrow numpy faker

# Den empfohlenen Datenanalyse-Stack verstehen

Beginnen wir damit, zu verstehen, was die einzelnen Komponenten bewirken und warum sie intestine zusammenarbeiten.

Parkett ist ein säulenförmiges Speicherformat, das ursprünglich für den entwickelt wurde Hadoop Ökosystem. Im Gegensatz zu zeilenbasierten Formaten wie CSV, bei denen jede Zeile ein vollständiger Datensatz ist, organisiert Parquet Daten nach Spalten. Dies magazine wie ein kleiner Unterschied erscheinen, hat aber enorme Auswirkungen auf die Analyse.

Wenn Sie eine Abfrage ausführen, die nur drei Spalten aus einer Tabelle mit fünfzig Spalten benötigt, können Sie mit Parquet nur diese drei Spalten lesen. Bei CSV müssen Sie jede Zeile vollständig lesen und dann die 47 Spalten, die Sie nicht benötigen, wegwerfen. Dies macht Parquet für typische analytische Abfragen schneller. Darüber hinaus lässt sich die spaltenbasierte Speicherung intestine komprimieren, da die Werte in derselben Spalte tendenziell ähnlich sind.

DuckDB ist eine eingebettete Analysedatenbank. Während SQLite DuckDB ist für transaktionale Arbeitslasten optimiert, die viele kleine Lese- und Schreibvorgänge erfordern. Es wurde speziell für analytische Abfragen entwickelt, die das Scannen großer Datenmengen, Aggregationen und Verknüpfungen erfordern. Der eingebettete Teil bedeutet, dass er innerhalb Ihres Python-Prozesses ausgeführt wird, sodass kein separater Datenbankserver installiert oder verwaltet werden muss.

Das Besondere an DuckDB für die Analyse ist, dass es Parquet-Dateien direkt abfragen kann. Sie müssen die Daten nicht zuerst in die Datenbank importieren. Richten Sie DuckDB auf eine Parquet-Datei, schreiben Sie SQL und es liest nur das, was es benötigt. Diese „Question-in-Place“-Funktion macht den gesamten Stack nützlich.

Sie können dies in Ihrer Python-Entwicklungsumgebung verwenden. Sie speichern Daten in Parquet-Dateien, Pandas übernimmt die Datenmanipulation, DuckDB führt analytische Abfragen aus und das gesamte Python-Ökosystem steht für Visualisierung, maschinelles Lernen und Automatisierung zur Verfügung.

# Erstellen eines Beispieldatensatzes

Wir werden einen E-Commerce-Datensatz verwenden. Sie können die verwenden data_generator.py-Skript um den Beispieldatensatz zu generieren oder Folgen Sie diesem Notizbuch.

Der Datensatz umfasst Kunden, die Bestellungen aufgeben, Bestellungen, die mehrere Artikel enthalten, und Produkte mit Kategorien und Preisen.

Die Daten haben referenzielle Integrität. Jede Bestellung verweist auf einen gültigen Kunden und jede Bestellposition verweist sowohl auf eine gültige Bestellung als auch auf ein gültiges Produkt. Dadurch können wir sinnvolle Verknüpfungen und Aggregationen durchführen.

# Daten in einer Parquet-Datei speichern

Bevor wir unsere Daten speichern, wollen wir verstehen, warum Parquet für Analysen effektiv ist. Wir haben die Vorteile von säulenförmigen Speicherformaten wie Parquet bereits besprochen, aber gehen wir noch einmal darauf ein, diesmal detaillierter.

In einer CSV-Datei werden Daten Zeile für Zeile gespeichert. Wenn Sie eine Million Zeilen mit jeweils 50 Spalten haben und nur eine Spalte analysieren möchten, müssen Sie dennoch alle 50 Millionen Werte lesen, um die Spalten zu überspringen, die Sie nicht benötigen. Das ist Verschwendung.

Wie wir jetzt wissen, speichert Parquet Daten Spalte für Spalte. Alle Werte für eine Spalte werden zusammen gespeichert. Wenn Sie eine Spalte abfragen, lesen Sie genau diese Spalte und nichts anderes. Bei analytischen Abfragen, die typischerweise eine kleine Anzahl von Spalten betreffen, ist dies viel schneller.

Auch die säulenförmige Speicherung lässt sich besser komprimieren. Werte in derselben Spalte neigen dazu, ähnlich zu sein – sie sind normalerweise alle Ganzzahlen, alle Datumsangaben oder alle aus derselben kategorialen Menge. Komprimierungsalgorithmen funktionieren bei ähnlichen Daten viel besser als bei Zufallsdaten.

Speichern wir unsere Daten als Parquet und sehen wir uns die Vorteile an:

# Save tables as Parquet information
customers_df.to_parquet('clients.parquet', engine="pyarrow", compression='snappy')
products_df.to_parquet('merchandise.parquet', engine="pyarrow", compression='snappy')
orders_df.to_parquet('orders.parquet', engine="pyarrow", compression='snappy')
order_items_df.to_parquet('order_items.parquet', engine="pyarrow", compression='snappy')

# Evaluate with CSV to see the distinction
customers_df.to_csv('clients.csv', index=False)
orders_df.to_csv('orders.csv', index=False)

import os

def get_size_mb(filename):
    return os.path.getsize(filename) / (1024 * 1024)

print("Storage Comparability:")
print(f"clients.csv:     {get_size_mb('clients.csv'):.2f} MB")
print(f"clients.parquet: {get_size_mb('clients.parquet'):.2f} MB")
print(f"Financial savings: {(1 - get_size_mb('clients.parquet')/get_size_mb('clients.csv'))*100:.1f}%n")

print(f"orders.csv:        {get_size_mb('orders.csv'):.2f} MB")
print(f"orders.parquet:    {get_size_mb('orders.parquet'):.2f} MB")
print(f"Financial savings: {(1 - get_size_mb('orders.parquet')/get_size_mb('orders.csv'))*100:.1f}%")

Ausgabe:

Storage Comparability:
clients.csv:     0.73 MB
clients.parquet: 0.38 MB
Financial savings: 48.5%

orders.csv:        3.01 MB
orders.parquet:    1.25 MB
Financial savings: 58.5%

Diese Kompressionsverhältnisse sind typisch. Parquet erreicht im Allgemeinen eine bessere Komprimierung als CSV. Die Komprimierung, die wir hier verwenden, ist Bissigbei dem Geschwindigkeit Vorrang vor maximaler Komprimierung hat.

Hinweis: Parquet unterstützt andere Codecs wie Gzipdas eine bessere Komprimierung bietet, aber langsamer ist, und Zstd für eine gute Steadiness zwischen Kompression und Geschwindigkeit.

# Parquet-Dateien mit DuckDB abfragen

Jetzt kommt der interessante Teil. Wir können diese Parquet-Dateien direkt mit SQL abfragen, ohne sie zuerst in eine Datenbank zu laden.

import duckdb

# Create a DuckDB connection
con = duckdb.join(database=":reminiscence:")

# Question the Parquet file immediately
question = """
SELECT
    customer_segment,
    COUNT(*) as num_customers,
    COUNT(*) * 100.0 / SUM(COUNT(*)) OVER () as share
FROM 'clients.parquet'
GROUP BY customer_segment
ORDER BY num_customers DESC
"""

end result = con.execute(question).fetchdf()
print("Buyer Distribution:")
print(end result)

Ausgabe:

Buyer Distribution:
  customer_segment  num_customers  share
0          Normal           5070       50.70
1             Fundamental           2887       28.87
2           Premium           2043       20.43

Schauen Sie sich die Abfragesyntax an: FROM 'clients.parquet'. DuckDB liest die Datei direkt. Es gibt keinen Importschritt, nein CREATE TABLE Anweisung und kein Warten auf das Laden der Daten. Sie schreiben SQL, DuckDB ermittelt aus der Datei, welche Daten es benötigt, und gibt Ergebnisse zurück.

In herkömmlichen Arbeitsabläufen müssten Sie eine Datenbank erstellen, Schemata definieren, Daten importieren, Indizes erstellen und schließlich eine Abfrage durchführen. Mit DuckDB und Parquet überspringen Sie das alles. Unter der Haube liest DuckDB die Metadaten der Parquet-Datei, um das Schema zu verstehen, und verwendet dann Prädikat-Pushdown, um das Lesen von Daten zu überspringen, die nicht mit Ihrem Schema übereinstimmen WHERE Klausel. Es liest nur die Spalten, die Ihre Abfrage tatsächlich verwendet. Bei großen Dateien werden Abfragen dadurch superschnell.

# Durchführen komplexer Analysen

Lassen Sie uns eine etwas komplexere analytische Abfrage ausführen. Wir analysieren die monatlichen Umsatztrends aufgeschlüsselt nach Kundensegmenten.

question = """
SELECT
    strftime(o.order_date, '%Y-%m') as month,
    c.customer_segment,
    COUNT(DISTINCT o.order_id) as num_orders,
    COUNT(DISTINCT o.customer_id) as unique_customers,
    ROUND(SUM(o.order_total), 2) as total_revenue,
    ROUND(AVG(o.order_total), 2) as avg_order_value
FROM 'orders.parquet' AS o
JOIN 'clients.parquet' AS c
  ON o.customer_id = c.customer_id
WHERE o.payment_status="accomplished"
GROUP BY month, c.customer_segment
ORDER BY month DESC, total_revenue DESC
LIMIT 15
"""

monthly_revenue = con.execute(question).fetchdf()
print("Latest Month-to-month Income by Section:")
print(monthly_revenue.to_string(index=False))

Ausgabe:

Latest Month-to-month Income by Section:
  month customer_segment  num_orders  unique_customers  total_revenue  avg_order_value
2026-01          Normal        2600              1468     1683223.68           647.39
2026-01             Fundamental        1585               857     1031126.44           650.55
2026-01           Premium         970               560      914105.61           942.38
2025-12          Normal        2254              1571     1533076.22           680.16
2025-12           Premium         885               613      921775.85          1041.55
2025-12             Fundamental        1297               876      889270.86           685.64
2025-11          Normal        1795              1359     1241006.08           691.37
2025-11           Premium         725               554      717625.75           989.83
2025-11             Fundamental        1012               767      682270.44           674.18
2025-10          Normal        1646              1296     1118400.61           679.47
2025-10           Premium         702               550      695913.24           991.33
2025-10             Fundamental         988               769      688428.86           696.79
2025-09          Normal        1446              1181      970017.17           670.83
2025-09           Premium         594               485      577486.81           972.20
2025-09             Fundamental         750               618      495726.69           660.97

Diese Abfrage gruppiert nach zwei Dimensionen (Monat und Section), aggregiert mehrere Metriken und filtert nach dem Zahlungsstatus. Es ist die Artwork von Abfrage, die Sie in der analytischen Arbeit ständig schreiben würden. Der strftime Funktion formatiert Datumsangaben direkt in SQL. Der ROUND Funktion bereinigt Dezimalstellen. Mehrere Aggregationen laufen effizient und liefern die erwarteten Ergebnisse.

# Mehrere Tabellen verbinden

Echte Analysen umfassen selten eine einzelne Tabelle. Kommen wir zu unseren Tischen, um eine geschäftliche Frage zu beantworten: Welche Produktkategorien generieren den meisten Umsatz und wie unterscheidet sich dieser je nach Kundensegment?

question = """
SELECT
    p.class,
    c.customer_segment,
    COUNT(DISTINCT oi.order_id) as num_orders,
    SUM(oi.amount) as units_sold,
    ROUND(SUM(oi.item_total), 2) as total_revenue,
    ROUND(AVG(oi.item_total), 2) as avg_item_value
FROM 'order_items.parquet' oi
JOIN 'orders.parquet' o ON oi.order_id = o.order_id
JOIN 'merchandise.parquet' p ON oi.product_id = p.product_id
JOIN 'clients.parquet' c ON o.customer_id = c.customer_id
WHERE o.payment_status="accomplished"
GROUP BY p.class, c.customer_segment
ORDER BY total_revenue DESC
LIMIT 20
"""

category_analysis = con.execute(question).fetchdf()
print("Income by Class and Buyer Section:")
print(category_analysis.to_string(index=False))

Gekürzte Ausgabe:

Income by Class and Buyer Section:
     class customer_segment  num_orders  units_sold  total_revenue  avg_item_value
  Electronics          Normal        4729      6431.0     6638814.75         1299.18
  Electronics           Premium        2597      3723.0     3816429.62         1292.39
  Electronics             Fundamental        2685      3566.0     3585652.92         1240.28
   Automotive          Normal        4506      5926.0     3050679.12          633.18
       Sports activities          Normal        5049      6898.0     2745487.54          497.55
...
...
     Clothes           Premium        3028      4342.0      400704.25          114.55
     Clothes             Fundamental        3102      4285.0      400391.18          117.49
        Books          Normal        6196      8511.0      252357.39           36.74

Diese Abfrage verknüpft drei Tabellen. DuckDB ermittelt automatisch die optimale Be a part of-Reihenfolge und Ausführungsstrategie. Beachten Sie, wie lesbar die SQL im Vergleich zu entsprechendem Pandas-Code ist. Bei komplexer analytischer Logik drückt SQL die Absicht häufig klarer aus als DataFrame-Operationen.

# Abfrageleistung verstehen

Vergleichen wir DuckDB mit Pandas für eine häufige Analyseaufgabe.

// Methode 1: Pandas verwenden

import time

# Analytical activity: Calculate buyer buy patterns
print("Efficiency Comparability: Buyer Buy Analysisn")

start_time = time.time()

# Merge dataframes
merged = order_items_df.merge(orders_df, on='order_id')
merged = merged.merge(products_df, on='product_id')

# Filter accomplished orders
accomplished = merged(merged('payment_status') == 'accomplished')

# Group and mixture
customer_patterns = accomplished.groupby('customer_id').agg({
    'order_id': 'nunique',
    'product_id': 'nunique',
    'item_total': ('sum', 'imply'),
    'class': lambda x: x.mode()(0) if len(x) > 0 else None
})

customer_patterns.columns = ('num_orders', 'unique_products', 'total_spent', 'avg_spent', 'favorite_category')
customer_patterns = customer_patterns.sort_values('total_spent', ascending=False).head(100)

pandas_time = time.time() - start_time

// Methode 2: Verwenden von DuckDB

start_time = time.time()

question = """
SELECT
    o.customer_id,
    COUNT(DISTINCT oi.order_id) as num_orders,
    COUNT(DISTINCT oi.product_id) as unique_products,
    ROUND(SUM(oi.item_total), 2) as total_spent,
    ROUND(AVG(oi.item_total), 2) as avg_spent,
    MODE(p.class) as favorite_category
FROM 'order_items.parquet' oi
JOIN 'orders.parquet' o ON oi.order_id = o.order_id
JOIN 'merchandise.parquet' p ON oi.product_id = p.product_id
WHERE o.payment_status="accomplished"
GROUP BY o.customer_id
ORDER BY total_spent DESC
LIMIT 100
"""

duckdb_result = con.execute(question).fetchdf()
duckdb_time = time.time() - start_time

print(f"Pandas execution time:  {pandas_time:.4f} seconds")
print(f"DuckDB execution time:  {duckdb_time:.4f} seconds")
print(f"Speedup: {pandas_time/duckdb_time:.1f}x quicker with DuckDBn")

print("Prime 5 clients by whole spent:")
print(duckdb_result.head().to_string(index=False))

Ausgabe:

Efficiency Comparability: Buyer Buy Evaluation

Pandas execution time:  1.9872 seconds
DuckDB execution time:  0.1171 seconds
Speedup: 17.0x quicker with DuckDB

Prime 5 clients by whole spent:
 customer_id  num_orders  unique_products  total_spent  avg_spent favorite_category
        8747           8               24     21103.21     879.30       Electronics
         617           9               27     19596.22     725.79       Electronics
        2579           9               18     17011.30     895.33            Sports activities
        6242           7               23     16781.11     729.61       Electronics
        5443           8               22     16697.02     758.96        Automotive

DuckDB ist etwa 17x schneller. Dieser Leistungsunterschied ist bei größeren Datensätzen stärker ausgeprägt. Der Pandas-Ansatz lädt alle Daten in den Speicher, führt mehrere Zusammenführungsvorgänge durch (die Kopien erstellen) und aggregiert sie dann. DuckDB liest direkt aus Parquet-Dateien, verschiebt Filter nach unten, um das Lesen unnötiger Daten zu vermeiden, und verwendet optimierte Be a part of-Algorithmen.

# Erstellen wiederverwendbarer Analytics-Abfragen

In der Produktionsanalyse führen Sie ähnliche Abfragen wiederholt mit unterschiedlichen Parametern aus. Lassen Sie uns eine wiederverwendbare Funktion erstellen, die den Finest Practices für diesen Workflow folgt.

def analyze_product_performance(con, class=None, min_revenue=None, date_from=None, top_n=20):
    """
    Analyze product efficiency with versatile filtering.

    This demonstrates how one can construct reusable analytical queries that may be
    parameterized for various use circumstances. In manufacturing, you'd construct a library
    of those features for widespread analytical questions.
    """

    # Construct the WHERE clause dynamically primarily based on parameters
    where_clauses = ("o.payment_status="accomplished"")

    if class:
        where_clauses.append(f"p.class = '{class}'")

    if date_from:
        where_clauses.append(f"o.order_date >= '{date_from}'")

    where_clause = " AND ".be part of(where_clauses)

    # Principal analytical question
    question = f"""
    WITH product_metrics AS (
        SELECT
            p.product_id,
            p.product_name,
            p.class,
            p.base_price,
            COUNT(DISTINCT oi.order_id) as times_ordered,
            SUM(oi.amount) as units_sold,
            ROUND(SUM(oi.item_total), 2) as total_revenue,
            ROUND(AVG(oi.unit_price), 2) as avg_selling_price,
            ROUND(SUM(oi.item_total) - (p.value * SUM(oi.amount)), 2) as revenue
        FROM 'order_items.parquet' oi
        JOIN 'orders.parquet' o ON oi.order_id = o.order_id
        JOIN 'merchandise.parquet' p ON oi.product_id = p.product_id
        WHERE {where_clause}
        GROUP BY p.product_id, p.product_name, p.class, p.base_price, p.value
    )
    SELECT
        *,
        ROUND(100.0 * revenue / total_revenue, 2) as profit_margin_pct,
        ROUND(avg_selling_price / base_price, 2) as price_realization
    FROM product_metrics
    """

    # Add income filter if specified
    if min_revenue:
        question += f" WHERE total_revenue >= {min_revenue}"

    question += f"""
    ORDER BY total_revenue DESC
    LIMIT {top_n}
    """

    return con.execute(question).fetchdf()

Diese Funktion führt Folgendes aus. Erstens baut es SQL dynamisch auf der Grundlage von Parametern auf und ermöglicht so eine versatile Filterung, ohne für jeden Fall separate Abfragen schreiben zu müssen. Zweitens verwendet es a Gemeinsamer Tabellenausdruck (CTE), um komplexe Logik in lesbare Schritte zu organisieren. Drittens berechnet es abgeleitete Kennzahlen wie Gewinnspanne und Preisrealisierung, die mehrere Quellspalten erfordern.

Bei der Gewinnberechnung werden die Kosten vom Umsatz subtrahiert, wobei Daten aus den Bestellpositions- und Produkttabellen verwendet werden. Diese Artwork der tabellenübergreifenden Berechnung ist in SQL unkompliziert, wäre jedoch bei mehreren Pandas-Operationen umständlich. DuckDB verarbeitet dies effizient in einer einzigen Abfrage.

Hier ist ein Beispiel, das die obige Funktion verwendet:

# Instance 1: Prime electronics merchandise
electronics = analyze_product_performance(con, class='Electronics', top_n=10)
print("Prime 10 Electronics Merchandise:")
print(electronics(('product_name', 'units_sold', 'total_revenue', 'profit_margin_pct')).to_string(index=False))

Ausgabe:

Prime 10 Electronics Merchandise:
        product_name  units_sold  total_revenue  profit_margin_pct
Electronics Merchandise 113       262.0      510331.81              38.57
Electronics Merchandise 154       289.0      486307.74              38.28
Electronics Merchandise 122       229.0      448680.64              38.88
Electronics Merchandise 472       251.0      444680.20              38.51
Electronics Merchandise 368       222.0      424057.14              38.96
Electronics Merchandise 241       219.0      407648.10              38.75
Electronics Merchandise 410       243.0      400078.65              38.31
Electronics Merchandise 104       233.0      400036.84              38.73
  Electronics Merchandise 2       213.0      382583.85              38.76
Electronics Merchandise 341       240.0      376722.94              38.94

Und hier ist ein weiteres Beispiel:

# Instance 2: Excessive-revenue merchandise throughout all classes
print("nnHigh-Income Merchandise (>$50k income):")
high_revenue = analyze_product_performance(con, min_revenue=50000, top_n=10)
print(high_revenue(('product_name', 'class', 'total_revenue', 'revenue')).to_string(index=False))

Ausgabe:

Excessive-Income Merchandise (>$50k income):
        product_name     class  total_revenue     revenue
Electronics Merchandise 113 Electronics      510331.81  196846.19
Electronics Merchandise 154 Electronics      486307.74  186140.78
Electronics Merchandise 122 Electronics      448680.64  174439.40
Electronics Merchandise 472 Electronics      444680.20  171240.80
Electronics Merchandise 368 Electronics      424057.14  165194.04
Electronics Merchandise 241 Electronics      407648.10  157955.25
Electronics Merchandise 410 Electronics      400078.65  153270.84
Electronics Merchandise 104 Electronics      400036.84  154953.46
  Electronics Merchandise 2 Electronics      382583.85  148305.15
Electronics Merchandise 341 Electronics      376722.94  146682.94

# Zusammenfassung

In diesem Artikel haben wir E-Commerce-Daten analysiert. Wir haben relationale Daten generiert, sie als Parquet gespeichert und mit DuckDB abgefragt. Die Leistungsvergleiche zeigten erhebliche Beschleunigungen im Vergleich zu herkömmlichen Pandas-Ansätzen.

Verwenden Sie diesen Stack, wenn Sie analytische Workloads für strukturierte Daten durchführen. Wenn Sie Metriken aggregieren, filtern, verknüpfen und berechnen, ist dies nützlich. Es eignet sich intestine für Daten, die sich stapelweise und nicht ständig ändern. Wenn Sie die gestrigen Verkäufe analysieren, monatliche Berichte verarbeiten oder historische Traits untersuchen, funktionieren die regelmäßig aktualisierten Parquet-Dateien hervorragend. Sie benötigen keine Dwell-Datenbank, die ständig Schreibvorgänge akzeptiert.

Allerdings ist dieser Stack nicht für alles geeignet:

  • Wenn Sie Echtzeitaktualisierungen mit vielen gleichzeitigen Autoren benötigen, benötigen Sie eine herkömmliche Datenbank mit ACID-Transaktionen
  • Wenn Sie eine Anwendung mit benutzerorientierten Abfragen erstellen, die Antwortzeiten im Millisekundenbereich erfordern, ist eine indizierte Datenbank besser
  • Wenn mehrere Benutzer gleichzeitig mit unterschiedlichen Zugriffsberechtigungen Abfragen durchführen müssen, bietet ein Datenbankserver eine bessere Kontrolle

Der Candy Spot ist analytische Arbeit an großen Datensätzen, bei denen Datenaktualisierungen in Stapeln erfolgen und Sie schnelle, versatile Abfragen und Analysen benötigen.

Viel Spaß beim Analysieren!

Bala Priya C ist ein Entwickler und technischer Redakteur aus Indien. Sie arbeitet gerne an der Schnittstelle von Mathematik, Programmierung, Datenwissenschaft und Inhaltserstellung. Zu ihren Interessen- und Fachgebieten gehören DevOps, Datenwissenschaft und Verarbeitung natürlicher Sprache. Sie liebt es zu lesen, zu schreiben, zu programmieren und Kaffee zu trinken! Derzeit arbeitet sie daran, zu lernen und ihr Wissen mit der Entwickler-Neighborhood zu teilen, indem sie Tutorials, Anleitungen, Meinungsbeiträge und mehr verfasst. Bala erstellt außerdem ansprechende Ressourcenübersichten und Programmier-Tutorials.



Von admin

Schreibe einen Kommentar

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