MEMEDIA SS25

05. DATA WORKSHOP

2025-05-13

Lecturer: Kim Albrecht

Summer 2025

Design Process

Fry, Benjamin. 2004. “Computational Information Design.”
Fry, Benjamin. 2004. “Computational Information Design.”
Fry, Benjamin. 2004. “Computational Information Design.”
Fry, Benjamin. 2004. “Computational Information Design.”

Data

UFO Sightings

Dieser Datensatz enthält über 80.000 Berichte über UFO-Sichtungen aus dem letzten Jahrhundert vom National UFO Reporting Center (NUFORC).

Source:
https://www.kaggle.com/datasets/NUFORC/ufo-sightings/data

Filter

OpenRefine

OpenRefine Tutorials: How to Create a New Project in OpenRefine
OpenRefine Tutorials: How to Create Text Facet and Filter

Represent

Slide 1 Slide 2 Slide 3 Slide 4 Slide 5
1 / 5

Tutorial: Daten zu Grafiken codieren

Einführung

Dieses Tutorial behandelt die grundlegenden Themen, die du brauchst, um interaktive und dynamische Visualisierungen zu erstellen. Folge dem Ablauf und probiere gerne die Codebeispiele aus. Es gibt viele Wege und Stile zu programmieren. Höre also nicht nur auf mich, sondern erkunde auch andere Perspektiven und Quellen. Hier ein paar Empfehlungen zum Einstieg:

Einrichtung deiner Umgebung

Benötigte Tools: Code-Editor: Wir verwenden Visual Studio Code für diese Übung. Installiere die Erweiterung Live Server, um deinen Fortschritt einfach im Browser anzeigen zu können. Wenn du bereits deine eigene Umgebung hast: Super! Solange du einen lokalen Server hast, mit dem du arbeiten kannst, ist alles gut.

Grundlagen in HTML, CSS und JavaScript

Um Visualisierungen mit d3.js zu erstellen, ist es wichtig, mit HTML, CSS und JavaScript vertraut zu sein.

Diese Präsentation erklärt die Grundkonzepte sehr gut.

HTML (Hypertext Markup Language)

HTML ist das Rückgrat von Webinhalten. Es strukturiert eine Webseite durch eine Reihe verschachtelter Elemente, die mit Tags beschrieben werden. Diese Tags sagen dem Browser, wie Inhalte dargestellt werden sollen.

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Basic HTML Page</title>
    </head>
    <body>
        <h1>Welcome to D3.js!</h1>
        <p>This is a simple HTML page.</p>
    </body>
</html>

Für eine Einführung in HTML empfehle ich dieses Video:

Basics of HTML

CSS (Cascading Style Sheets)

CSS wird verwendet, um HTML-Inhalte zu gestalten und visuell aufzuwerten. Es ermöglicht dir, Farben, Schriftarten, Abstände und Layouts anzuwenden, um eine ansprechende Benutzeroberfläche zu schaffen.

h1 {
    color: red;
}

p {
    font-size: 10px;
}

Für eine Einführung in CSS empfehle ich dieses Video:

Basics of CSS

JavaScript

JavaScript ist eine vielseitige Skriptsprache, die Interaktivität und dynamisches Verhalten auf Webseiten ermöglicht. Es kann HTML-Elemente manipulieren, auf Benutzereingaben reagieren und Daten laden.

<script>
    console.log('Hello World!');
</script>

Grundlagen

HTML-Grundgerüst

Lass uns mit einem grundlegenden HTML-Gerüst starten und es Schritt für Schritt erweitern. Am Ende des Tutorials haben wir den vollständigen Code für die Visualisierung.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Data Visualization with d3.js</title>
    <script src="https://d3js.org/d3.v7.min.js"></script>
    <style>

    </style>
</head>
<body>
    <script>
        // JavaScript code will go here
    </script>
</body>
</html>

Daten laden

D3 ermöglicht das Laden externer Datensätze in verschiedenen Formaten wie CSV, JSON oder TSV. Für unsere Übung verwenden wir einen Datensatz über weltweite UFO-Sichtungen mit verschiedenen Datenarten: kategorisch, numerisch, ortsbezogen und zeitlich.

Daten laden wir mit d3.tsv(). Beispiel:

d3.tsv("ufo-sightings-1910-1990.tsv").then(function(data) {
    console.log(data);
    // Hier beginnt die Visualisierung...
});

Minimales Beispiel

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Data Visualization with d3.js</title>
    <script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
    <script>
        const svg = d3.select("body")
            .append("svg")
            .attr("width", 500)
            .attr("height", 500);

        d3.tsv("ufo-sightings-1910-1990.tsv").then(function(data) {
            svg.selectAll("circle")
                .data(data)
                .enter()
                .append("circle")
                .attr("cx", 250)
                .attr("cy", 250)
                .attr("r", d => d.duration/10)
                .style("fill", "none")
                .style("stroke", "black");
        });
    </script>
</body>
</html>

Probiere, diese Datei zu verändern:

Verfeinerungen

Margins und SVG vorbereiten

Die bisherige Methode funktioniert, aber es ist hilfreich, Margins für dein SVG-Element hinzuzufügen. Anstelle von:

const svg = d3.select("body")
    .append("svg")
    .attr("width", 500)
    .attr("height", 500);

…nutzen wir eine bessere Struktur:

// Set margins and dimensions
const margin = {top: 20, right: 20, bottom: 20, left: 20};
const width = 800 - margin.left - margin.right;
const height = 600 - margin.top - margin.bottom;

// Create SVG element
const svg = d3.select("body")
    .append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate("+margin.left+","+margin.top+")");

Arbeiten mit Skalen

Eines der wichtigsten Konzepte in d3.js sind Skalen. Sie wirken harmlos, sind aber zentral. In meiner eigenen Arbeit gehören sie zu den meistgenutzten Funktionen in d3.js.

References:
Learn D3: Scales
d3-scale

Die grundlegende Idee von Skalen ist die Abbildung von Daten auf Ausgabewerte. Wenn du z. B. ein Ereignis aus 500 Jahren darstellen willst, musst du diese Zeitspanne auf den Bildschirm bringen. Dafür sind Skalen da.

Lineare Skalen

Für quantitative Daten:

// Linear scale for circle size (duration)
const sizeScale = d3.scaleLinear()
    .domain([0, d3.max(data, d => +d.duration)])
    .range([2, 20]);

Zeit-Skalen

Für Zeitdaten:

// Time scale for x-axis (datetime)
const xScale = d3.scaleTime()
    .domain(d3.extent(data, d => new Date(d.datetime)))
    .range([0, width]);

Band-Skalen

Für kategorische/ordinale Daten (Positionskodierung):

// Band scale for y-axis (shape)
const yScale = d3.scaleBand()
    .domain([...new Set(data.map(d => d.shape))])
    .range([0, height])
    .padding(0.1);

Ordinale Skalen

Für Kategorien wie Länder:

// Color scale for country
const colorScale = d3.scaleOrdinal(d3.schemeCategory10)
    .domain([...new Set(data.map(d => d.country))]);

Skalierte Visualisierungselemente hinzufügen

Now, add circles based on the dataset using the newly defined scales:

// Add circles
svg.selectAll("circle")
    .data(data)
    .enter()
    .append("circle")
    .attr("cx", d => xScale(new Date(d.datetime)))
    .attr("cy", d => yScale(d.shape))
    .attr("r", d => sizeScale(+d.duration))
    .attr("fill", d => colorScale(d.country));

Achsen hinzufügen

// Create x-axis (time scale)
const xAxis = d3.axisBottom(xScale);
svg.append("g")
   .attr("transform", `translate(0, ${height})`)
   .call(xAxis);

// Create y-axis (band scale)
const yAxis = d3.axisLeft(yScale);
svg.append("g")
   .call(yAxis);

Animationen hinzufügen

    .attr("r", 0) 
    .transition()
    .duration(1000)
    .attr("r", d => sizeScale(+d.duration))

Gesamter Code

Hier ist der vollständige HTML-, CSS- und JavaScript-Code, der alle Teile zusammenbringt, um die komplette Visualisierung zu erstellen:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Data Visualization with d3.js</title>
    <script src="https://d3js.org/d3.v7.min.js"></script>
    <style>

    </style>
</head>
<body>
    <script>
        // Set margins and dimensions
        const margin = {top: 20, right: 30, bottom: 50, left: 80};
        const width = 800 - margin.left - margin.right;
        const height = 600 - margin.top - margin.bottom;

        // Create SVG element
        const svg = d3.select("body")
            .append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate("+margin.left+","+margin.top+")");

        d3.tsv("ufo-sightings-1910-1990.tsv").then(function(data) {
            console.log(data);

            // Linear scale for circle size (duration)
            const sizeScale = d3.scaleLinear()
                .domain([0, d3.max(data, d => +d.duration)])
                .range([2, 20]);

            // Band scale for y-axis (shape)
            const yScale = d3.scaleBand()
                .domain([...new Set(data.map(d => d.shape))])
                .range([0, height])
                .padding(0.1);

            // Time scale for x-axis (datetime)
            const xScale = d3.scaleTime()
                .domain(d3.extent(data, d => new Date(d.datetime)))
                .range([0, width]);

            // Color scale for country
            const colorScale = d3.scaleOrdinal(d3.schemeCategory10)
                .domain([...new Set(data.map(d => d.country))]);

            // Add circles based on data
            svg.selectAll("circle")
               .data(data)
               .enter()
               .append("circle")
               .attr("cx", d => xScale(new Date(d.datetime)))
               .attr("cy", d => yScale(d.shape))
               .attr("r", d => sizeScale(+d.duration))
               .attr("fill", d => colorScale(d.country));

            // Create x-axis (time scale)
            const xAxis = d3.axisBottom(xScale);
            svg.append("g")
               .attr("transform", `translate(0, ${height})`)
               .call(xAxis);

            // Create y-axis (band scale)
            const yAxis = d3.axisLeft(yScale);
            svg.append("g")
               .call(yAxis);
        });
    </script>
</body>
</html>

UFO d3.js Code