Praxisbeispiel - Telko Vertragskundenabgang-Vorhersage - Daten simulieren/kreieren

Da der Original-Datensatz von kaggle schon recht weit vorbereitet ist als Feature-Matrix, möchten wir unseren eigenen dazu passenden Datensatz erstellen, um zu sehen, wie Feature Engineering auf dynamischen Datensätzen aussieht.

Hierfür nehmen wir uns das Beispiel des Kunden-Services.

Wiefolgt sind die Schritte für die Kreierung eines solchen simulierten Datensatzes:

  1. Original-Datensatz laden

  2. Stichtag und Vertragsbeginn definieren: Setze den Stichtag auf den 31.12.2024. Für jeden Kunden berechnen wir einen simulierten Vertragsstart, indem wir den Stichtag um die Anzahl der Monate (aus der Spalte tenure) zurückrechnen.

  3. Anzahl der Tickets pro Kunde simulieren: Wir simulieren bzw bestimmen für jeden Kunden zufällig (z. B. basierend auf einer Poisson-Verteilung oder einer zufälligen Zahl), wie viele Tickets (also Interaktions-Threads) im Betrachtungszeitraum generiert werden.

  4. Ticket-Interaktionen erzeugen: Für jedes Ticket erstellen wir mehrere Interaktionen (z. B. eine erste Anfrage und dann ein bis zwei Follow-ups). Dabei werden folgende Spalten befüllt:

    • ticket_id: Eindeutige Kennung (zum Beispiel als Kombination aus Customer-ID und einem Zähler).

    • customer_id: Übernimmt den Wert aus dem Telco-Datensatz.

    • time_request: Zufälliger Zeitpunkt der Anfrage zwischen Vertragsstart und Stichtag.

    • time_reply: Ein Zeitpunkt, der einige Stunden oder Tage nach time_request liegt.

    • channel: Zufällig ausgewählter Kommunikationskanal (z. B. “Email”, “Hotline”, “On-site”, “Chat”, “Social Media”).

    • request und reply: Simulierte Texte (z. B. “Problem mit Rechnung” bzw. “Problem gelöst”).

    • solved: Boolean, der anzeigt, ob das Problem mit der Antwort gelöst wurde (z. B. basierend auf Stichwörtern im Antworttext).

    • original_request: True, wenn es sich um die erste Interaktion eines Tickets handelt, sonst False.

    • original_ticket_id: Bei der ersten Interaktion bleibt dieser Wert None, ansonsten verweist er auf die ursprüngliche Ticket-ID.

  5. Zusätzliche Spalten (optional: Optional können wir weitere Informationen wie beispielsweise den bearbeitenden Agenten, Ticket-Priorität oder Notizen hinzufügen.

Datensatz

Original Datensatz:

https://www.kaggle.com/datasets/blastchar/telco-customer-churn

[1]:
import sys
# !{sys.executable} -m pip install kagglehub
# !{sys.executable} -m pip install plotly
# !{sys.executable} -m pip install missingno
[2]:
import kagglehub

[3]:
import pandas as pd
import numpy as np
import random
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta


pd.set_option('display.max_columns', None)
[4]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import warnings
[5]:
from sklearn.preprocessing import StandardScaler, LabelEncoder

from sklearn.model_selection import train_test_split

from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn.neural_network import MLPClassifier
from sklearn.ensemble import AdaBoostClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.linear_model import LogisticRegression

from sklearn import metrics
from sklearn.metrics import roc_curve
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix, classification_report

# from xgboost import XGBClassifier
# from catboost import CatBoostClassifier
[6]:
# Download data from Kaggle
path = kagglehub.dataset_download("blastchar/telco-customer-churn")

print("Path to files:", path)
Path to files: /Users/veit/.cache/kagglehub/datasets/blastchar/telco-customer-churn/versions/1
[7]:
path_file = "~/.cache/kagglehub/datasets/blastchar/telco-customer-churn/versions/1/WA_Fn-UseC_-Telco-Customer-Churn.csv"
print(path_file)
~/.cache/kagglehub/datasets/blastchar/telco-customer-churn/versions/1/WA_Fn-UseC_-Telco-Customer-Churn.csv

Datensatz

Lade den Original-Datensatz

[8]:
df = pd.read_csv(path_file)
df
[8]:
customerID gender SeniorCitizen Partner Dependents tenure PhoneService MultipleLines InternetService OnlineSecurity OnlineBackup DeviceProtection TechSupport StreamingTV StreamingMovies Contract PaperlessBilling PaymentMethod MonthlyCharges TotalCharges Churn
0 7590-VHVEG Female 0 Yes No 1 No No phone service DSL No Yes No No No No Month-to-month Yes Electronic check 29.85 29.85 No
1 5575-GNVDE Male 0 No No 34 Yes No DSL Yes No Yes No No No One year No Mailed check 56.95 1889.5 No
2 3668-QPYBK Male 0 No No 2 Yes No DSL Yes Yes No No No No Month-to-month Yes Mailed check 53.85 108.15 Yes
3 7795-CFOCW Male 0 No No 45 No No phone service DSL Yes No Yes Yes No No One year No Bank transfer (automatic) 42.30 1840.75 No
4 9237-HQITU Female 0 No No 2 Yes No Fiber optic No No No No No No Month-to-month Yes Electronic check 70.70 151.65 Yes
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
7038 6840-RESVB Male 0 Yes Yes 24 Yes Yes DSL Yes No Yes Yes Yes Yes One year Yes Mailed check 84.80 1990.5 No
7039 2234-XADUH Female 0 Yes Yes 72 Yes Yes Fiber optic No Yes Yes No Yes Yes One year Yes Credit card (automatic) 103.20 7362.9 No
7040 4801-JZAZL Female 0 Yes Yes 11 No No phone service DSL Yes No No No No No Month-to-month Yes Electronic check 29.60 346.45 No
7041 8361-LTMKD Male 1 Yes No 4 Yes Yes Fiber optic No No No No No No Month-to-month Yes Mailed check 74.40 306.6 Yes
7042 3186-AJIEK Male 0 No No 66 Yes No Fiber optic Yes No Yes Yes Yes Yes Two year Yes Bank transfer (automatic) 105.65 6844.5 No

7043 rows × 21 columns

Der Datensatz enthält Informationen über:

  • ob der Kunde innerhalb des letzten Monats gekündigt hat - Spalte „Churn“

  • Dienste, für die sich jeder Kunde angemeldet hat - „PhoneService“, „MultipleLines“, „InternetService“, „OnlineSecurity“, „OnlineBackup“, „DeviceProtection“, „TechSupport“ sowie „StreamingTV“ und „StreamingMovies“.

  • Informationen zum Kundenkonto - „tenure“ wie lange der Kunde bereits Kunde ist, „Contract“ (Vertrag), „PaperlessBilling“ (papierlose Abrechnung), „PaymentMethod“ (Zahlungsmethode), „MonthlyCharges“ (monatliche Gebühren) und „TotalCharges“ (Gesamtgebühren).

  • Demografische Informationen über Kunden - „gender“ (Geschlecht), „SeniorCitizen“ (Alter) und ob sie „Partner“ (Partner) und „Dependents“ (Familienangehörige) haben.

[9]:
# Für Reproduzierbarkeit definieren wir den selben Seed für den Randomisierung

np.random.seed(42)
random.seed(42)

Stichtag

Für unsere Simulation definieren wir einen Stichtag - das ist der Tag, an dem der Datensatz gezogen wird. Das ist auch die Referenz für das Startdatum der Tenure eines Kunden, somit dürften keine Datenpunkte vor dem berechneten Start-datum oder nach diesem Stichtag kreiert werden.

Der Stichtag in diesem Beispiel-Code ist der 2024-12-31.

[10]:
# 2. Stichtag definieren
stichtag = pd.to_datetime("2024-12-31")
stichtag
[10]:
Timestamp('2024-12-31 00:00:00')
[11]:
# Berechne den Vertragsstart als: stichtag - tenure in Monaten
df["contract_start"] = df["tenure"].apply(lambda t: stichtag - relativedelta(months=int(t)))
df[["customerID", "tenure", "contract_start"]].head()
[11]:
customerID tenure contract_start
0 7590-VHVEG 1 2024-11-30
1 5575-GNVDE 34 2022-02-28
2 3668-QPYBK 2 2024-10-31
3 7795-CFOCW 45 2021-03-31
4 9237-HQITU 2 2024-10-31

Funktion zur Berechnung des Reply-Zeitpunkts

Hier definieren wir eine Funktion get_reply_time, die für einen gegebenen Anfrage-Zeitpunkt (request_time) den Reply-Zeitpunkt simuliert.

Die Bedingungen sind:

  • Ist die Anfrage am Stichtag, erfolgt die Antwort zwangsläufig am selben Tag.

  • Sonst wird zufällig entschieden, ob die Antwort am selben Tag oder am nächsten Tag erfolgt.

  • Falls der nächste Tag den Stichtag überschreiten würde, wird ebenfalls der gleiche Tag gewählt.

[12]:
def get_reply_time(request_time, stichtag):
    """
    Berechnet einen Reply-Zeitpunkt, der entweder am selben Tag
    oder am Tag nach der Anfrage liegt, unter Berücksichtigung des Stichtags.
    """
    # Wenn die Anfrage bereits am Stichtag erfolgt, muss die Antwort am selben Tag erfolgen.
    if request_time.date() >= stichtag.date():
        reply_day_offset = 0
    else:
        reply_day_offset = random.choice([0, 1])

    if reply_day_offset == 0:
        # Antwort am selben Tag: Wähle eine zufällige Verzögerung, sodass die Antwort
        # zwischen 1 Stunde nach der Anfrage und bis zum Tagesende erfolgt.
        end_of_day = request_time.replace(hour=23, minute=59, second=59)
        max_delay_seconds = int((end_of_day - request_time).total_seconds())
        # Falls genügend Zeit vorhanden ist, mindestens 1 Stunde Verzögerung, sonst minimal
        min_delay = 3600 if max_delay_seconds >= 3600 else 60
        delay_seconds = random.randint(min_delay, max_delay_seconds) if max_delay_seconds >= min_delay else 0
        reply_time = request_time + timedelta(seconds=delay_seconds)
    else:
        # Antwort am nächsten Tag: Stelle sicher, dass der nächste Tag den Stichtag nicht überschreitet.
        next_day = request_time + timedelta(days=1)
        if next_day > stichtag:
            # Fallback: Antworte am selben Tag
            return get_reply_time(request_time, stichtag)
        # Wähle eine zufällige Uhrzeit am nächsten Tag
        random_hour = random.randint(0, 23)
        random_minute = random.randint(0, 59)
        random_second = random.randint(0, 59)
        reply_time = datetime.combine(next_day.date(), datetime.min.time()) + timedelta(hours=random_hour, minutes=random_minute, seconds=random_second)

    return reply_time

# Teste die Funktion einmal:
test_request = datetime(2024, 12, 30, 15, 0, 0)
print("Anfragezeit:", test_request)
print("Antwortzeit:", get_reply_time(test_request, stichtag))
Anfragezeit: 2024-12-30 15:00:00
Antwortzeit: 2024-12-30 16:13:39

Vor-test: Simuliere Interaktionen für einen einzelnen Kunden (Beispiel anhand des ersten Kunden)

[13]:
# Wähle den ersten Kunden aus dem Datensatz
customer_row = df.iloc[0]
customer_id = customer_row["customerID"]
contract_start = customer_row["contract_start"]
customer_row
[13]:
customerID                   7590-VHVEG
gender                           Female
SeniorCitizen                         0
Partner                             Yes
Dependents                           No
tenure                                1
PhoneService                         No
MultipleLines          No phone service
InternetService                     DSL
OnlineSecurity                       No
OnlineBackup                        Yes
DeviceProtection                     No
TechSupport                          No
StreamingTV                          No
StreamingMovies                      No
Contract                 Month-to-month
PaperlessBilling                    Yes
PaymentMethod          Electronic check
MonthlyCharges                    29.85
TotalCharges                      29.85
Churn                                No
contract_start      2024-11-30 00:00:00
Name: 0, dtype: object
[14]:
# Bestimme zufällig die Anzahl der Tickets (z.B. mittels einer Poisson-Verteilung)
num_tickets = np.random.poisson(lam=2)
print("Anzahl der Tickets für den Kunden:", num_tickets)
Anzahl der Tickets für den Kunden: 4
[15]:
# Wir definieren die verschiedenen Kanäle, die für den Kunden zur Verfügung steht, den Kundenservice zu erreichen

list_channels = ["Email", "Hotline", "On-site", "Chat", "Social Media"]
[16]:
# Der Einfachheitshalber definieren wir für diese Simulation die möglichen Optionen für Request-Text und Reply-Text vor:

# Liste an request-Optionen (die häufigsten Request-Gründe)
list_request = ["Problem mit Rechnung", "Internet funktioniert nicht", "Frage zum Vertrag", "Beschwerde über Kundenservice", "Technische Störung"]

# Liste an request-Optionen (die häufigsten Request-Gründe)
list_reply = ["Problem gelöst", "Weitere Informationen benötigt", "Ticket geschlossen", "Anfrage wird bearbeitet"]
[17]:
# Wir definieren die möglichen Zustände eines Tickets
list_zustand = ["gelöst", "geschlossen"]
[18]:
# Initiere eine Liste, um die Interaktionen dieses Kunden zu speichern, sowie ticket-counter
interactions = []
ticket_counter = 0
[19]:
# Für diesen ersten Testkunden erstellen wir nun für die definierte Anzahl an Tickets die Inhalte:

for t in range(num_tickets):
    ticket_counter += 1
    ticket_id = f"{customer_id}_T{ticket_counter}"

    # Zufälliger Startzeitpunkt des Tickets zwischen Vertragsstart und Stichtag
    total_days = (stichtag - contract_start).days
    ticket_start_date = contract_start + timedelta(days=random.randint(0, total_days))

    # Setze den initialen "last_reply_time" auf ticket_start_date, wird im Laufe des Prozesses geupdated
    last_reply_time = ticket_start_date

    # Bestimme zufällig, wie viele Interaktionen (1 bis 3) dieses Ticket hat
    num_interactions = random.randint(1, 3)

    for i in range(num_interactions):
        is_original = (i == 0)
        if is_original:
            request_time = ticket_start_date
        else:
            # Für Folgeinteraktionen: Anfragezeit ist einige Tage nach der letzten Antwort,
            # aber achte darauf, dass wir nicht über den Stichtag hinausgehen.
            max_days = (stichtag - last_reply_time).days

            # Wenn max_days 0 ist, muss es am selben Tag bleiben
            additional_days = random.randint(0, 1) if max_days >= 1 else 0
            request_time = last_reply_time + timedelta(days=additional_days)

        # Berechne den Reply-Zeitpunkt mit der neuen Funktion
        time_reply = get_reply_time(request_time, stichtag)
        last_reply_time = time_reply  # Update für die nächste Iteration

        channel = random.choice(list_channels)
        request_text = random.choice(list_request)
        reply_text = random.choice(list_reply)
        solved = any(keyword in reply_text.lower() for keyword in list_zustand)

        interaction = {
            "ticket_id": ticket_id,
            "customer_id": customer_id,
            "time_request": request_time,
            "time_reply": time_reply,
            "channel": channel,
            "request": request_text,
            "reply": reply_text,
            "solved": solved,
            "original_request": is_original,
            "original_ticket_id": None if is_original else ticket_id
        }
        print(interaction)
        interactions.append(interaction)
{'ticket_id': '7590-VHVEG_T1', 'customer_id': '7590-VHVEG', 'time_request': Timestamp('2024-12-17 00:00:00'), 'time_reply': Timestamp('2024-12-17 06:04:49'), 'channel': 'Email', 'request': 'Technische Störung', 'reply': 'Problem gelöst', 'solved': True, 'original_request': True, 'original_ticket_id': None}
{'ticket_id': '7590-VHVEG_T2', 'customer_id': '7590-VHVEG', 'time_request': Timestamp('2024-12-27 00:00:00'), 'time_reply': Timestamp('2024-12-27 04:24:40'), 'channel': 'Hotline', 'request': 'Internet funktioniert nicht', 'reply': 'Problem gelöst', 'solved': True, 'original_request': True, 'original_ticket_id': None}
{'ticket_id': '7590-VHVEG_T3', 'customer_id': '7590-VHVEG', 'time_request': Timestamp('2024-12-12 00:00:00'), 'time_reply': datetime.datetime(2024, 12, 13, 7, 28, 37), 'channel': 'On-site', 'request': 'Problem mit Rechnung', 'reply': 'Weitere Informationen benötigt', 'solved': False, 'original_request': True, 'original_ticket_id': None}
{'ticket_id': '7590-VHVEG_T3', 'customer_id': '7590-VHVEG', 'time_request': datetime.datetime(2024, 12, 14, 7, 28, 37), 'time_reply': datetime.datetime(2024, 12, 15, 8, 9, 13), 'channel': 'On-site', 'request': 'Problem mit Rechnung', 'reply': 'Problem gelöst', 'solved': True, 'original_request': False, 'original_ticket_id': '7590-VHVEG_T3'}
{'ticket_id': '7590-VHVEG_T3', 'customer_id': '7590-VHVEG', 'time_request': datetime.datetime(2024, 12, 16, 8, 9, 13), 'time_reply': datetime.datetime(2024, 12, 16, 15, 41, 19), 'channel': 'On-site', 'request': 'Technische Störung', 'reply': 'Ticket geschlossen', 'solved': True, 'original_request': False, 'original_ticket_id': '7590-VHVEG_T3'}
{'ticket_id': '7590-VHVEG_T4', 'customer_id': '7590-VHVEG', 'time_request': Timestamp('2024-12-02 00:00:00'), 'time_reply': datetime.datetime(2024, 12, 3, 17, 7, 59), 'channel': 'Chat', 'request': 'Problem mit Rechnung', 'reply': 'Ticket geschlossen', 'solved': True, 'original_request': True, 'original_ticket_id': None}
{'ticket_id': '7590-VHVEG_T4', 'customer_id': '7590-VHVEG', 'time_request': datetime.datetime(2024, 12, 4, 17, 7, 59), 'time_reply': datetime.datetime(2024, 12, 4, 18, 45, 58), 'channel': 'Email', 'request': 'Internet funktioniert nicht', 'reply': 'Ticket geschlossen', 'solved': True, 'original_request': False, 'original_ticket_id': '7590-VHVEG_T4'}
{'ticket_id': '7590-VHVEG_T4', 'customer_id': '7590-VHVEG', 'time_request': datetime.datetime(2024, 12, 4, 18, 45, 58), 'time_reply': datetime.datetime(2024, 12, 4, 23, 42, 34), 'channel': 'Email', 'request': 'Beschwerde über Kundenservice', 'reply': 'Ticket geschlossen', 'solved': True, 'original_request': False, 'original_ticket_id': '7590-VHVEG_T4'}
[20]:
# Erstelle einen DataFrame für diesen Kunden
interactions_df = pd.DataFrame(interactions)
interactions_df
[20]:
ticket_id customer_id time_request time_reply channel request reply solved original_request original_ticket_id
0 7590-VHVEG_T1 7590-VHVEG 2024-12-17 00:00:00 2024-12-17 06:04:49 Email Technische Störung Problem gelöst True True NaN
1 7590-VHVEG_T2 7590-VHVEG 2024-12-27 00:00:00 2024-12-27 04:24:40 Hotline Internet funktioniert nicht Problem gelöst True True NaN
2 7590-VHVEG_T3 7590-VHVEG 2024-12-12 00:00:00 2024-12-13 07:28:37 On-site Problem mit Rechnung Weitere Informationen benötigt False True NaN
3 7590-VHVEG_T3 7590-VHVEG 2024-12-14 07:28:37 2024-12-15 08:09:13 On-site Problem mit Rechnung Problem gelöst True False 7590-VHVEG_T3
4 7590-VHVEG_T3 7590-VHVEG 2024-12-16 08:09:13 2024-12-16 15:41:19 On-site Technische Störung Ticket geschlossen True False 7590-VHVEG_T3
5 7590-VHVEG_T4 7590-VHVEG 2024-12-02 00:00:00 2024-12-03 17:07:59 Chat Problem mit Rechnung Ticket geschlossen True True NaN
6 7590-VHVEG_T4 7590-VHVEG 2024-12-04 17:07:59 2024-12-04 18:45:58 Email Internet funktioniert nicht Ticket geschlossen True False 7590-VHVEG_T4
7 7590-VHVEG_T4 7590-VHVEG 2024-12-04 18:45:58 2024-12-04 23:42:34 Email Beschwerde über Kundenservice Ticket geschlossen True False 7590-VHVEG_T4

Simuliere/Kreiere Interaktionen für alle Kunden

[21]:
all_interactions = []

for _, row in df.iterrows():
    customer_id = row["customerID"]
    contract_start = row["contract_start"]
    num_tickets = np.random.poisson(lam=2)
    ticket_counter = 0

    for t in range(num_tickets):
        ticket_counter += 1
        ticket_id = f"{customer_id}_T{ticket_counter}"
        num_interactions = random.randint(1, 3)
        total_days = (stichtag - contract_start).days
        ticket_start_date = contract_start + timedelta(days=random.randint(0, total_days))
        last_reply_time = ticket_start_date

        for i in range(num_interactions):
            is_original = (i == 0)
            if is_original:
                request_time = ticket_start_date
            else:
                max_days = (stichtag - last_reply_time).days
                additional_days = random.randint(0, 1) if max_days >= 1 else 0
                request_time = last_reply_time + timedelta(days=additional_days)

            time_reply = get_reply_time(request_time, stichtag)
            last_reply_time = time_reply
            channel = random.choice(list_channels)
            request_text = random.choice(list_request)
            reply_text = random.choice(list_reply)

            solved = any(keyword in reply_text.lower() for keyword in list_zustand)

            interaction = {
                "ticket_id": ticket_id,
                "customer_id": customer_id,
                "time_request": request_time,
                "time_reply": time_reply,
                "channel": channel,
                "request": request_text,
                "reply": reply_text,
                "solved": solved,
                "original_request": is_original,
                "original_ticket_id": None if is_original else ticket_id
            }
            all_interactions.append(interaction)
[22]:
# Erstelle den DataFrame für die simulierte "kunden-service"-Tabelle
df_kunden_service = pd.DataFrame(all_interactions)

print(df_kunden_service.shape)

df_kunden_service.head(10)
(28158, 10)
[22]:
ticket_id customer_id time_request time_reply channel request reply solved original_request original_ticket_id
0 7590-VHVEG_T1 7590-VHVEG 2024-12-23 00:00:00 2024-12-23 14:28:40 On-site Internet funktioniert nicht Ticket geschlossen True True NaN
1 7590-VHVEG_T1 7590-VHVEG 2024-12-23 14:28:40 2024-12-23 20:20:22 Hotline Internet funktioniert nicht Anfrage wird bearbeitet False False 7590-VHVEG_T1
2 5575-GNVDE_T1 5575-GNVDE 2023-09-03 00:00:00 2023-09-03 12:48:24 Email Internet funktioniert nicht Problem gelöst True True NaN
3 5575-GNVDE_T1 5575-GNVDE 2023-09-04 12:48:24 2023-09-05 08:04:13 Social Media Frage zum Vertrag Weitere Informationen benötigt False False 5575-GNVDE_T1
4 5575-GNVDE_T2 5575-GNVDE 2024-12-16 00:00:00 2024-12-17 20:29:09 On-site Internet funktioniert nicht Weitere Informationen benötigt False True NaN
5 5575-GNVDE_T2 5575-GNVDE 2024-12-18 20:29:09 2024-12-19 18:25:23 Hotline Internet funktioniert nicht Anfrage wird bearbeitet False False 5575-GNVDE_T2
6 5575-GNVDE_T2 5575-GNVDE 2024-12-19 18:25:23 2024-12-19 20:25:15 Hotline Internet funktioniert nicht Anfrage wird bearbeitet False False 5575-GNVDE_T2
7 5575-GNVDE_T3 5575-GNVDE 2022-07-08 00:00:00 2022-07-09 12:38:29 Social Media Frage zum Vertrag Problem gelöst True True NaN
8 5575-GNVDE_T3 5575-GNVDE 2022-07-09 12:38:29 2022-07-10 20:21:07 On-site Beschwerde über Kundenservice Weitere Informationen benötigt False False 5575-GNVDE_T3
9 5575-GNVDE_T3 5575-GNVDE 2022-07-11 20:21:07 2022-07-11 22:33:02 Social Media Internet funktioniert nicht Problem gelöst True False 5575-GNVDE_T3
[23]:
# Tabelle abspeichern, um auch anderweitig weiternutzen zu können
df_kunden_service.to_csv("kunden_service.csv", index=False)