Fehlerklassen und -arten

Fehler – Fehlerarten und Fehlerklassen(*) – eine Übersicht

Fehlerarten beschreiben, was in den Daten schief ist (z. B. „ungültiges Datum“, „Duplikat“, „fehlender Datensatz“). Fehlerklassen beschreiben, welcher Art der Fehler ist – also woran er erkannt wird und warum er in BI-Analysen besonders kritisch ist.

Kurslogik (Einheit 2): Die Einteilung hilft, passende Gegenmaßnahmen abzuleiten: syntaktische Fehler sind häufig regelbasiert automatisierbar, semantische Fehler brauchen Domänenwissen/Business Rules, Coverage-Fehler sind besonders gefährlich, weil sie unbemerkt Trends und Kennzahlen verzerren können.

 

Wir unterteilen in folgende Fehlerklassen:

1) Syntaktische Fehler (Form/Regeln):
Werte sind formal/technisch fehlerhaft oder uneinheitlich (Format, Datentyp, erlaubte Zeichen/Wertebereiche). Typisch: Parsing/Typisierung scheitert → NULL/BLANK, Fehler in Power Query, fehlerhafte Joins.

2) Semantische Fehler (Bedeutung):
Werte sind formal gültig, aber fachlich falsch oder widersprüchlich (z. B. negativer Umsatz ohne Retourenlogik, Statuslogik falsch, Dubletten mit widersprüchlichen Attributen). Besonders gefährlich: Reports wirken „sauber“, KPIs sind inhaltlich falsch.

3) Coverage-Fehler (Abdeckung/Vollständigkeit):
Daten fehlen – Attribute, Datensätze, Zeiträume oder Beziehungen (Orphans). Das erzeugt Bias und verzerrt Zeitreihen, Forecasts, Segmentierungen.

Zuordnung (wie von dir vorgegeben):

  • Semantische Fehlerarten: Verschmutzungen, Noisy Data, Redundanz
  • Syntaktische Fehlerarten: Unzulässige Werte, Unregelmäßigkeiten
  • Coverage-Fehlerarten: Fehlende Werte, Unvollständige Werte
 
      
🔎

Tipp: Zeile anklicken, um sie zu markieren. Suche filtert alle Fehler-Tabellen gleichzeitig.

Standard: Power BI/DAX ist eingeblendet. Du kannst pro Sprache Beispiel-Daten und konkrete Prüf-/Bereinigungsschritte einblenden.

 

Power BI / DAX – Beispiel-Daten & Setup

Import-Tabelle Sales (Textspalten enthalten bewusst Probleme). Zusätzlich wird eine Kalendertabelle Date genutzt. Die Tabellenzeilen referenzieren genau diese Felder.

Sales (Beispiel)
SaleID | CustomerID | DateText     | AmountText | Zip   | Status     | Source | StatusCode
1      | C001       | 2025-01-05   | 120.50     | 10115 | OK         | CRM    | A
2      | C002       | 05.01.2025   | 99,95      | 80A01 | Cancelled  | ERP    | A
3      | C003       | 2025/13/01   | fifty      | 50667 | OK         | CRM    | A
4      | C004       | (blank)      | -10.00     | 50667 | OK         | CRM    | A
// Date Table (für Zeitreihen & Coverage-Checks)
Date = CALENDAR(DATE(2025,1,1), DATE(2025,1,10))

Tipp: Parsing/Typisierung gehört in Power BI meist in Power Query. DAX wird hier als „Modell-/Kontrollsicht“ gezeigt (Checks, Flags, KPIs).

 

Beispiele (Tabellenlogik)

Die Fehlerklassen sind Überschriften der Tabellen. Die Fehlerarten sind Zeilen. Spalten: (1) Fehlerart, (2) Beschreibung, (3) Kursbezug, (4–6) konkrete Beispiele in R, Power BI/DAX und Python.

Tipp für Praxis/Prüfung: Wenn du eine Fehlerart erkennst, formuliere immer direkt eine Regel (Validierung) und einen Behandlungsweg (korrigieren, mappen, quarantänisieren, imputieren, 0/NA bewusst ausweisen).

 

Semantische Fehler (Bedeutung) – Fehlerarten

Fehlerart Beschreibung Kursbezug? Beispiel in R Beispiel in Power BI/DAX Beispiel in Python
Verschmutzungen
semantisch
Werte sind formal gültig, aber fachlich falsch oder widersprüchlich. Typisch: unplausible Werte (z.B. negativer Umsatz ohne Retourenlogik), falsche Zuordnung (Kunde/Produkt), Statuslogik wird ignoriert. Datenqualität/Business Rules: „formal ok“ ≠ „fachlich korrekt“; Gefahr: KPIs werden falsch.
# Betrag parsebar machen
sales$AmountNum <- as.numeric(gsub(",", ".", sales$AmountText))

# Business Rule: negativer Betrag nur bei Retouren-/Storno-Status erlaubt
sales$SemDirtyFlag <- !is.na(sales$AmountNum) & sales$AmountNum < 0 & sales$Status == "OK"

sales[sales$SemDirtyFlag, c("SaleID","Status","AmountText","AmountNum")]

Behandlung: korrigieren (wenn regelbasiert) oder Quarantäne/Fehlerlog.

AmountNum =
VAR t = Sales[AmountText]
VAR norm = SUBSTITUTE(t, ",", ".")
RETURN IFERROR(VALUE(norm), BLANK())

SemDirtyFlag =
VAR a = [AmountNum]
RETURN IF(NOT ISBLANK(a) && a < 0 && Sales[Status] = "OK", TRUE(), FALSE())

Im Report als DQ-KPI: Anteil semantisch verdächtiger Zeilen.

df["AmountNum"] = pd.to_numeric(
  df["AmountText"].str.replace(",", ".", regex=False),
  errors="coerce"
)

df["SemDirtyFlag"] = df["AmountNum"].notna() & (df["AmountNum"] < 0) & df["Status"].eq("OK")
df.loc[df["SemDirtyFlag"], ["SaleID","Status","AmountText","AmountNum"]]
Noisy Data
semantisch
Zufällige Störungen/Messrauschen oder starke Ausreißer, die Muster verzerren (z.B. Sensorwerte, Klickdaten). In BI oft sichtbar als „Peaks“, die sich nicht durch Prozesse erklären lassen. Datenprofiling & Ausreißerbehandlung: Risiko für Forecast/Modelle und Fehlinterpretation in Reports.
# Beispiel: Ausreißer-Flag über IQR (benötigt AmountNum)
q <- quantile(sales$AmountNum, probs=c(.25,.75), na.rm=TRUE)
iqr <- q[2]-q[1]
lower <- q[1] - 1.5*iqr
upper <- q[2] + 1.5*iqr

sales$NoisyFlag <- !is.na(sales$AmountNum) & (sales$AmountNum < lower | sales$AmountNum > upper)
sales[sales$NoisyFlag, c("SaleID","AmountNum")]

Behandlung: winsorize, glätten, oder fachlich erklären/ausklammern.

// Einfacher Check im Modell: Abweichung vom gleitenden Mittel
// (Für echte Rolling-Berechnungen i.d.R. besser in Power Query / DWH)
AvgAmount = AVERAGE(Sales[AmountNum])

NoisyFlag =
VAR a = Sales[AmountNum]
RETURN IF(NOT ISBLANK(a) && ABS(a - [AvgAmount]) > 3 * STDEVX.P(ALL(Sales), Sales[AmountNum]), TRUE(), FALSE())

In Power BI visuell: Zeitreihe + Referenzlinie + Ausreißer-Count als KPI.

# Z-Score-Check (grob)
m = df["AmountNum"].mean(skipna=True)
s = df["AmountNum"].std(skipna=True)

df["NoisyFlag"] = df["AmountNum"].notna() & ((df["AmountNum"] - m).abs() > 3*s)
df.loc[df["NoisyFlag"], ["SaleID","AmountNum"]]
Redundanz
semantisch
Mehrfach vorkommende oder widersprüchliche Informationen (Dubletten, doppelte Kunden/Bestellungen, doppelte Events). Gefährlich: doppelte Summen/KPIs, widersprüchliche Dimensionen. Redundanz/Dubletten als DQ-Thema; betrifft ETL-Integration und konforme Dimensionen.
# Beispiel: Dubletten nach (CustomerID, DateText, AmountText)
key <- paste(sales$CustomerID, sales$DateText, sales$AmountText, sep="|")
sales$DupFlag <- duplicated(key) | duplicated(key, fromLast=TRUE)

sales[sales$DupFlag, c("SaleID","CustomerID","DateText","AmountText")]

Behandlung: Golden-Record-Regel (Priorität Quelle, Timestamp, Status) + Logging.

// Dubletten-Check im Modell (einfach): gleiche (CustomerID, DateText, AmountText)
DupCount =
VAR kCust = Sales[CustomerID]
VAR kDate = Sales[DateText]
VAR kAmt  = Sales[AmountText]
RETURN CALCULATE(
  COUNTROWS(Sales),
  FILTER(ALL(Sales),
    Sales[CustomerID]=kCust &&
    Sales[DateText]=kDate &&
    Sales[AmountText]=kAmt
  )
)

DupFlag = IF([DupCount] > 1, TRUE(), FALSE())

Besser: Dubletten im ETL/Power Query entfernen + Audit-Tabelle führen.

# Dubletten markieren
cols = ["CustomerID","DateText","AmountText"]
df["DupFlag"] = df.duplicated(cols, keep=False)
df.loc[df["DupFlag"], ["SaleID"] + cols]
 

Syntaktische Fehler (Form/Regeln) – Fehlerarten

Fehlerart Beschreibung Kursbezug? Beispiel in R Beispiel in Power BI/DAX Beispiel in Python
Unzulässige Werte
syntaktisch
Wert verletzt definierte Domäne/Regel: ungültiges Datum, Zahl als Text, PLZ mit Buchstaben, Wertebereich verletzt. Ergebnis: Typisierung/Parsing scheitert oder liefert NA/BLANK. Regelbasiert gut prüfbar (Datentyp, Range, Regex). Häufiger ETL-Härtungsfall.
# Multi-Format Datum parsen + ungültige Werte werden NA
parse_date_multi <- function(x){
  d1 <- as.Date(x, format="%Y-%m-%d")
  d2 <- as.Date(x, format="%d.%m.%Y")
  d3 <- as.Date(x, format="%Y/%m/%d")
  out <- d1
  out[is.na(out)] <- d2[is.na(out)]
  out[is.na(out)] <- d3[is.na(out)]
  out
}

sales$Date <- parse_date_multi(sales$DateText)

# Zahl als Text (Komma/Punkt/Text)
sales$AmountNum <- as.numeric(gsub(",", ".", sales$AmountText))

# PLZ-Regel (5 Ziffern)
sales$ZipOk <- grepl("^[0-9]{5}$", sales$Zip)

sales[, c("DateText","Date","AmountText","AmountNum","Zip","ZipOk")]
ParsedDate =
VAR t = Sales[DateText]
VAR iso = IFERROR(DATEVALUE(t), BLANK())
VAR de  =
  IF(ISBLANK(iso),
    IFERROR(
      DATE(VALUE(RIGHT(t,4)), VALUE(MID(t,4,2)), VALUE(LEFT(t,2))),
      BLANK()
    ),
    BLANK()
  )
VAR slash =
  IF(ISBLANK(iso) && ISBLANK(de),
    IFERROR(
      DATE(VALUE(LEFT(t,4)), VALUE(MID(t,6,2)), VALUE(RIGHT(t,2))),
      BLANK()
    ),
    BLANK()
  )
RETURN COALESCE(iso,de,slash)

AmountNum =
VAR t = Sales[AmountText]
VAR norm = SUBSTITUTE(t, ",", ".")
RETURN IFERROR(VALUE(norm), BLANK())

ZIP-Check besser in Power Query; DAX-Checks als Flags/KPIs nutzen.

# Datum robust (mehrere Formate)
df["Date"] = pd.to_datetime(df["DateText"], errors="coerce", format="%Y-%m-%d")
m = df["Date"].isna()
df.loc[m, "Date"] = pd.to_datetime(df.loc[m, "DateText"], errors="coerce", format="%d.%m.%Y")
m = df["Date"].isna()
df.loc[m, "Date"] = pd.to_datetime(df.loc[m, "DateText"], errors="coerce", format="%Y/%m/%d")

# Betrag
df["AmountNum"] = pd.to_numeric(df["AmountText"].str.replace(",", ".", regex=False), errors="coerce")

# PLZ Regex
df["ZipOk"] = df["Zip"].str.fullmatch(r"\d{5}").fillna(False)

df[["DateText","Date","AmountText","AmountNum","Zip","ZipOk"]]
Unregelmäßigkeiten
syntaktisch
Uneinheitliche Darstellung desselben Sachverhalts: gemischte Schreibweisen/Codes/Trennzeichen (z.B. „DE“, „Deutschland“, „GER“; Dezimalpunkt vs. -komma; unterschiedliche Datumsformate). Formal oft noch parsebar – aber inkonsistent. Standardisierung/Harmonisierung (Domänen, Mappings) als Kernaufgabe in ETL & DQ.
# Beispiel: Länder-Codes vereinheitlichen (Mapping)
country_map <- data.frame(
  raw = c("DE","Deutschland","GER"),
  std = c("DE","DE","DE"),
  stringsAsFactors = FALSE
)

# Angenommen: sales$CountryRaw existiert
# sales <- merge(sales, country_map, by.x="CountryRaw", by.y="raw", all.x=TRUE)

# Dezimaltrennzeichen vereinheitlichen (bereits genutzt)
sales$AmountNormText <- gsub(",", ".", sales$AmountText)

Ziel: konsistente Codes, konsistente Formate, dokumentierte Mapping-Regeln.

// Beispiel: Mapping-Tabelle nutzen (Source/StatusCode → UnifiedStatus)
UnifiedStatus =
LOOKUPVALUE(
  RefStatus[UnifiedStatus],
  RefStatus[Source], Sales[Source],
  RefStatus[Code],   Sales[StatusCode]
)

Unregelmäßigkeiten möglichst vor dem Modell in Power Query/DWH standardisieren.

# Beispiel: Mapping per Dictionary
mapping = {"DE":"DE", "Deutschland":"DE", "GER":"DE"}
# df["CountryStd"] = df["CountryRaw"].map(mapping).fillna("UNKNOWN")

# Dezimaltrennzeichen normieren
df["AmountNormText"] = df["AmountText"].str.replace(",", ".", regex=False)
 

Coverage-Fehler (Vollständigkeit/Abdeckung) – Fehlerarten

Fehlerart Beschreibung Kursbezug? Beispiel in R Beispiel in Power BI/DAX Beispiel in Python
Fehlende Werte
coverage
Einzelne Attributwerte fehlen (NULL/NA/BLANK) – z.B. Datum leer, Betrag nicht vorhanden, Pflichtfeld nicht befüllt. Gefahr: Filter/Joins/KPIs werden still verfälscht. Vollständigkeit als DQ-Kriterium; systematisch monitoren (Missing-Rate pro Feld).
# Missing Rate je Feld
missing_rate <- sapply(sales, function(x) mean(is.na(x) | x=="", na.rm=TRUE))
missing_rate

# Beispiel: fehlende Datumstexte
sales[is.na(sales$Date) | sales$DateText=="", c("SaleID","DateText")]
MissingDateRate =
DIVIDE(
  COUNTROWS(FILTER(Sales, ISBLANK(Sales[DateText]) || ISBLANK(Sales[ParsedDate]))),
  COUNTROWS(Sales)
)

Ideal: Missing-Rate als Qualitäts-KPI im DQ-Report.

# Missing Rate pro Spalte
(df.isna() | df.eq("")).mean()

# Zeilen mit fehlendem Datum
df.loc[df["DateText"].eq("") | df["Date"].isna(), ["SaleID","DateText","Date"]]
Unvollständige Werte
coverage
Datensätze/Beziehungen sind unvollständig: z.B. Kunde existiert, aber keine Sales; Sales ohne passenden Kunden („Orphans“); Zeitreihenlücken (Tage/Monate ohne Daten) – Ergebnis: Bias/Verzerrung. Coverage-Checks via Mengen-/Referenzabgleich (Anti-Join), Kalenderraster erzwingen, Orphans sichtbar machen.
# Anti-Join ohne dplyr (base R): Kunden ohne Sales
customers <- data.frame(CustomerID=c("C001","C002","C003","C004","C005"))
missing_sales <- customers[!customers$CustomerID %in% unique(sales$CustomerID), ]
missing_sales

# Zeitlücken (Kalender erzwingen)
all_days <- seq(as.Date("2025-01-01"), as.Date("2025-01-10"), by="day")
daily <- aggregate(AmountNum ~ Date, data=sales, sum, na.rm=TRUE)
calendar <- data.frame(Date=all_days)
out <- merge(calendar, daily, by="Date", all.x=TRUE)
out$AmountNum[is.na(out$AmountNum)] <- 0
out
// Kunden ohne Sales (Set-Operation)
CustomersWithoutSales =
EXCEPT(
  VALUES(Customers[CustomerID]),
  VALUES(Sales[CustomerID])
)

// Zeitlücken sichtbar: Date-Tabelle verwenden + "Elemente ohne Daten anzeigen"
Revenue := COALESCE(SUM(Sales[AmountNum]), 0)
# Kunden ohne Sales
customers = pd.DataFrame({"CustomerID":["C001","C002","C003","C004","C005"]})
missing = customers[~customers["CustomerID"].isin(df["CustomerID"].unique())]
missing

# Zeitlücken füllen (bewusst!)
df_daily = (
  df.dropna(subset=["Date","AmountNum"])
    .groupby("Date")["AmountNum"]
    .sum()
)
idx = pd.date_range("2025-01-01","2025-01-10", freq="D")
df_daily = df_daily.reindex(idx, fill_value=0)
df_daily
 

Praxis-Check (Einheit-2-Denke): Behandle Fehler nicht „still“. Gute BI-Praxis ist: (1) Regeln definieren, (2) messen (DQ-KPIs), (3) protokollieren (Run/Counts), (4) bewusst behandeln (korrigieren/mappen/quarantänisieren/0 vs NA), (5) rückkoppeln (Quelle/Prozess).

*) Hinweis zu Begriffen: In der Alltagssprache werden „Fehler“ und „Bias“ oft vermischt. Für BI ist wichtig: Coverage-Fehler können systematische Verzerrungen erzeugen (z.B. fehlende Regionen/Zeiträume), während andere Fehler eher als Datenmüll/Inkonsistenz auftreten.
**) BI-Kursbezug (Einheit 2): Die Einteilung in Fehlerklassen/Fehlerarten unterstützt die Auswahl von Qualitätsmaßnahmen im ETL/KDD/Reporting: syntaktisch (Regeln/Parsing), semantisch (Business Rules/Mappings), coverage (Abgleich/Vollständigkeit/Kalender/Orphans).
***) Als "BI-Kurs" wird hier insbesondere das Master-Modul Business Intelligence (FernUni Hagen) verstanden. Die Spalte „Kursbezug?“ dient zur Orientierung, ob ein Punkt eher als Werkzeugdetail oder als prüfungs-/konzeptrelevanter Kern (DQ/ETL/KDD) zu verstehen ist.

Mini-Merksatz: Syntaktisch = Form/Regeln, Semantisch = Bedeutung/Business Rule, Coverage = Vollständigkeit/Abdeckung (Bias-Risiko).