Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
2108 views
Kernel: Python 3 (Ubuntu Linux)

Визуальный анализ данных

Подключаем необходимые библиотеки.

import numpy as np import scipy as sp import pandas as pd import matplotlib.pyplot as plt %matplotlib inline import seaborn as sns

Считываем датасет.

data = pd.read_csv("telecom-churn.csv")

Проверяем, всё ли правильно считалось и "распарсилось".

data.head()

Можно получить сводку и общее представление о типах данных.

data.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 3333 entries, 0 to 3332 Data columns (total 21 columns): state 3333 non-null object account length 3333 non-null int64 area code 3333 non-null int64 phone number 3333 non-null object international plan 3333 non-null object voice mail plan 3333 non-null object number vmail messages 3333 non-null int64 total day minutes 3333 non-null float64 total day calls 3333 non-null int64 total day charge 3333 non-null float64 total eve minutes 3333 non-null float64 total eve calls 3333 non-null int64 total eve charge 3333 non-null float64 total night minutes 3333 non-null float64 total night calls 3333 non-null int64 total night charge 3333 non-null float64 total intl minutes 3333 non-null float64 total intl calls 3333 non-null int64 total intl charge 3333 non-null float64 customer service calls 3333 non-null int64 churn 3333 non-null bool dtypes: bool(1), float64(8), int64(8), object(4) memory usage: 524.1+ KB

Целевая переменная: churn (лояльность абонента). Это категориальный (более конкретно — бинарный) признак. Попробуем узнать, как распределены его значения.

data['churn'].value_counts()
False 2850 True 483 Name: churn, dtype: int64

Видим, что 2850 из 3333 абонентов — лояльные. А сколько это в процентах?..

data['churn'].value_counts(normalize=True)
False 0.855086 True 0.144914 Name: churn, dtype: float64

Визуализируем это.

data['churn'].value_counts(normalize=True).plot(kind='bar', title='Признак churn');
Image in a Jupyter notebook

Нам также может быть интересно, у скольких наших клиентов подключён роуминг.

data['international plan'].value_counts(normalize=True).plot(kind='bar');
Image in a Jupyter notebook

А как обстоят дела у нелояльных пользователей (churn=1)?

churn_users = data[data['churn'] == True] churn_users['international plan'].value_counts(normalize=True).plot(kind='bar');
Image in a Jupyter notebook

Видим, что процент клиентов с роумингом выше, чем в общей выборке.

Можем предположить, что бинарные признаки international plan и churn коррелируют. Нарисуем теперь их вместе.

pd.crosstab(data['churn'], data['international plan'], margins=True)
sns.countplot(x='international plan', hue='churn', data=data);
Image in a Jupyter notebook

Большинство клиентов, у которых был подключён роуминг, от нас ушли!

data.groupby('international plan')['churn'].count()
international plan no 3010 yes 323 Name: churn, dtype: int64

Посмотрим на распределение признака account length.

sns.distplot(data['account length']);
Image in a Jupyter notebook

Похоже на нормальное распределение!

Что можно сказать о связи между account length и лояльностью?

data.groupby('churn')['account length'].mean()
churn False 100.793684 True 102.664596 Name: account length, dtype: float64
data.groupby('churn')['account length'].std()
churn False 39.88235 True 39.46782 Name: account length, dtype: float64
data.groupby('churn')['account length'].median()
churn False 100 True 103 Name: account length, dtype: int64

На первый взгляд, никак не связаны.

fig, ax = plt.subplots(1, 2, sharey=True) sns.distplot(data[data['churn'] == False]['account length'], ax=ax[0]).set_title('Лояльные'); sns.distplot(churn_users['account length'], ax=ax[1]).set_title('Ушедшие');
Image in a Jupyter notebook

На второй взгляд тоже.

Теперь посмотрим, связаны ли длительности дневных и ночных звонков.

sns.regplot(data['total day minutes'], data['total night minutes']);
Image in a Jupyter notebook

А как насчёт количества звонков?

sns.regplot(data['total day calls'], data['total night calls']);
Image in a Jupyter notebook

Пока никакой связи не видно.

Построим корреляционную матрицу для числовых признаков.

numeric_data = data.select_dtypes(['int64', 'float64'])
numeric_data.head()
corr_matrix = numeric_data.drop('area code', axis=1).corr() corr_matrix
sns.heatmap(corr_matrix);
Image in a Jupyter notebook
sns.pairplot(numeric_data[['total day minutes', 'total day calls', 'total day charge']]);
Image in a Jupyter notebook