Исследовательский анализ данных (EDA) – это подход к анализу наборов данных для обобщения их основных характеристик, часто с использованием визуальных методов. Статистическая модель может использоваться или нет, но в первую очередь EDA предназначен для того, чтобы увидеть, что данные могут сказать нам помимо формального моделирования или задачи проверки гипотез.

В этом блоге мы возьмем пример набора данных Haberman Survival и проанализируем данные с помощью различных типов графиков и функций. Мы также выполняем математические операции, такие как среднее, медиана, стандартное отклонение, чтобы больше узнать о данных. Все это мы будем делать с помощью библиотек python и ML.

Давайте начнем…

Релевантная информация:

Набор данных содержит случаи из исследования, которое проводилось в период с 1958 по 1970 год в больнице Биллингс Чикагского университета о выживаемости пациентов, перенесших операцию по поводу рака молочной железы.

это содержит:-

  1. 305 точек данных/ряд.
  2. 4 функция, включая метку класса.

Цель:

Классифицировать/прогнозировать выживаемость пациенток, перенесших операцию по поводу рака молочной железы.

Информация об атрибутах:

Есть 4 функции, включая метку класса/зависимую переменную.

  1. Возраст пациента на момент операции (числовой).
  2. Год операции пациента (год — 1900, числовой).
  3. Количество обнаруженных положительных вспомогательных узлов (числовое).
  4. Статус выживания (атрибут класса) 1 = пациент прожил 5 лет или дольше 2 = пациент умер в течение 5 лет.

Постановка цели — это ключ к EDA, который структурирует ваши мысли во время всего анализа. Здесь цель состоит в том, чтобы предсказать, выживет ли пациент через 5 лет или нет, исходя из возраста пациента, года лечения и количества положительных лимфатических узлов.

Конфигурация среды:

Импортируйте необходимые пакеты и загрузите набор данных.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()

Загрузите набор данных:

cancer_df = pd.read_csv(‘haberman.csv’,header=None, names=[‘age’,’year_of_treatment’,’positive_lymph_nodes’,’survival_status_after_5_years’])
print(cancer_df.head())

Подготовка данных:

print(cancer_df.info())

Наблюдения:

  1. В этом наборе данных нет пропущенных данных. Таким образом, нет необходимости делать вменение данных.
  2. Тип данных столбца «survival_status_after_5_years» — целое число. Его необходимо преобразовать в категориальный тип данных.
  3. Значения столбца «survival_status_after_5_years» не имеют смысла. Следовательно, они отображаются как «да» (выжили через 5 лет) и «нет» (не выжили через 5 лет).

Проверьте уникальные значения целевого столбца. Измените значения целевого столбца, чтобы они были осмысленными и категоричными.

print(list(cancer_df[‘survival_status_after_5_years’].unique()))

[1, 2]

cancer_df[‘survival_status_after_5_years’] = cancer_df[‘survival_status_after_5_years’].map({1:”Yes”,2:”no”})
cancer_df[‘survival_status_after_5_years’] = cancer_df[‘survival_status_after_5_years’].astype(‘category’)
print(cancer_df.head())

print(cancer_df.info())

Статистика высокого уровня:

Сводная статистика, описывающая центральность и дисперсию, используется для понимания сути признаков.

print(cancer_df.describe())

print(“Number of rows: “+ str(cancer_df.shape[0]))
print(“Number of coloms: “+ str(cancer_df.shape[1]))
print(“Colomns: “+”, “.join(cancer_df.columns))
print(“Target variable distribution”)
print(cancer_df.iloc[:,-1].value_counts())
print(“*”*50)
print(cancer_df.iloc[:,-1].value_counts(normalize = True))

Наблюдения:

  1. Возраст больных колеблется от 30 до 83 лет, в среднем 52 года.
  2. Хотя максимальное количество наблюдаемых положительных лимфатических узлов составляет 52, почти 75% пациентов имеют менее 5 положительных лимфатических узлов и почти 25% пациентов не имеют положительных лимфатических узлов.
  3. Набор данных содержит лишь небольшое количество записей (306).
  4. Целевой столбец несбалансирован, 73 % значений — «да».

Одномерный анализ (pdf, cdf, boxplot и скрипичный график)

Одномерный анализ — это простейшая форма анализа данных. «Uni» означает «один», «variate» означает «переменная или числовая переменная», то есть, другими словами, ваши данные имеют только одну переменную. Он не имеет дело с причинами или отношениями (в отличие от регрессии), и его основная цель — описать; он берет данные, обобщает эти данные и находит закономерности в данных.

PDF (функция плотности вероятности):

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

  • Обычно точки данных группируются в бины, и высота столбцов, представляющих каждую группу, увеличивается с увеличением количества точек данных, лежащих в этой группе. (гистограмма).
  • Функция плотности вероятности (PDF) — это вероятность того, что переменная принимает значение x. (сглаженная версия гистограммы).
  • Оценка плотности ядра (KDE) — это способ оценки PDF. Площадь под кривой KDE равна 1.
  • Здесь высота столбца обозначает процент точек данных в соответствующей группе.
sns
.FacetGrid(cancer_df, hue = “survival_status_after_5_years”,size = 5).map(sns.distplot,”age”).add_legend()
plt.title(“Histogram of age”)
plt.ylabel(“Density”)
plt.show()

sns.FacetGrid(cancer_df, hue = “survival_status_after_5_years”, size = 5).map(sns.distplot,”year_of_treatment”).add_legend()
plt.title(“Histogram of year_of_treatment”)
plt.ylabel(“Density”)
plt.show()

sns.FacetGrid(cancer_df,hue = “survival_status_after_5_years”,size = 5).map(sns.distplot,”positive_lymph_nodes”).add_legend()
plt.title(“Histogram of positive_lymph_nodes”)
plt.ylabel(“Density”)
plt.show()

Наблюдения:

На всех графиках функции сильно накладываются друг на друга.

CDF (кумулятивная распределенная функция):

Кумулятивная функция распределения (CDF) — это вероятность того, что переменная принимает значение, меньшее или равное x.

one = cancer_df.loc[cancer_df[“survival_status_after_5_years”] == “Yes”]
two = cancer_df.loc[cancer_df[“survival_status_after_5_years”] == “no”]
label = [“pdf to class 1”,”cdf of class 1",”pdf to class 2",”cdf of class 2"]
counts,bin_edges = np.histogram(one[“age”],bins=10,density = True)
pdf = counts/(sum(counts))
cdf = np.cumsum(pdf)
plt.title(“pdf and cdf for age”)
plt.xlabel(“age”)
plt.ylabel(“% of person’s”)
plt.plot(bin_edges[1:],pdf)
plt.plot(bin_edges[1:],cdf)
counts,bin_edges = np.histogram(two[“age”],bins=10,density = True)
pdf = counts/(sum(counts))
cdf = np.cumsum(pdf)
plt.plot(bin_edges[1:],pdf)
plt.plot(bin_edges[1:],cdf)
plt.legend(label)
plt.show()

label = [“pdf to class 1”,”cdf of class 1",”pdf to class 2",”cdf of class 2"]
counts,bin_edges = np.histogram(one[“year_of_treatment”],bins=10,density = True)
pdf = counts/(sum(counts))
cdf = np.cumsum(pdf)
plt.title(“pdf and cdf for year_of_treatment”)
plt.xlabel(“year_of_treatment”)
plt.ylabel(“% of person’s”)
plt.plot(bin_edges[1:],pdf)
plt.plot(bin_edges[1:],cdf)
counts,bin_edges = np.histogram(two[“year_of_treatment”],bins=10,density = True)
pdf = counts/(sum(counts))
cdf = np.cumsum(pdf)
plt.plot(bin_edges[1:],pdf)
plt.plot(bin_edges[1:],cdf)
plt.legend(label)
plt.show()

label = [“pdf to class 1”,”cdf of class 1",”pdf to class 2",”cdf of class 2"]
counts,bin_edges = np.histogram(one[“positive_lymph_nodes”],bins=10,density = True)
pdf = counts/(sum(counts))
cdf = np.cumsum(pdf)
plt.title(“pdf and cdf for positive_lymph_nodes”)
plt.xlabel(“positive_lymph_nodes”)
plt.ylabel(“% of person’s”)
plt.plot(bin_edges[1:],pdf)
plt.plot(bin_edges[1:],cdf)
counts,bin_edges = np.histogram(two[“positive_lymph_nodes”],bins=10,density = True)
pdf = counts/(sum(counts))
cdf = np.cumsum(pdf)
plt.plot(bin_edges[1:],pdf)
plt.plot(bin_edges[1:],cdf)
plt.legend(label)
plt.show()

Среднее значение, дисперсия и стандартное отклонение:

print(“Means:”)
Yes = cancer_df.loc[cancer_df[“survival_status_after_5_years”] == “Yes”]
no = cancer_df.loc[cancer_df[“survival_status_after_5_years”] == “no”]
print(np.mean((Yes[“age”])))
print(np.mean((no[“age”])))
print(“\n Std-dev:”)
print(np.std(Yes[“age”]))
print(np.std(no[“age”]))

Медиана, процентиль, квантиль, IQR, MAD:

print(“\n Medians:”)
print(np.median(Yes[“age”]))
print(np.median(no[“age”]))
print(“\n Quantiles”)
print(np.percentile(Yes[“age”],np.arange(0,100,25)))
print(np.percentile(no[“age”],np.arange(0,100,25)))
print(“\n 90th Percentiles:”)
print(np.percentile(Yes[“age”],90))
print(np.percentile(no[“age”],90))
from statsmodels import robust
print (“\nMedian Absolute Deviation”)
print(robust.mad(Yes[“age”]))
print(robust.mad(no[“age”]))

Сюжеты коробки:

Коробчатая диаграмма занимает меньше места и визуально представляет собой пятизначную сводку точек данных в рамке. Выбросы отображаются в виде точек вне поля.

  1. Q1–1,5*МКР.
  2. Q1 (25-й процентиль).
  3. Q2 (50-й процентиль или медиана).
  4. Q3 (75-й процентиль).
  5. Q3 + 1,5 * межквартильный диапазон IQR = Q3 - Q1.
sns.boxplot(x =”survival_status_after_5_years”,y = “age”,hue = “survival_status_after_5_years”,data = cancer_df).set_title(“Box plot for survival_status and age”)
plt.show()

sns.boxplot(x= “survival_status_after_5_years”,y = “year_of_treatment”,hue = “survival_status_after_5_years”,data = cancer_df).set_title(“Box plot for survival_status and year of treatement “)
plt.show()

sns.boxplot(x= “survival_status_after_5_years”,y = “positive_lymph_nodes”,hue = “survival_status_after_5_years”,data = cancer_df).set_title(“Box plot for survival_status and year of treatement “)
plt.show()

Сюжеты для скрипки:

  1. Скрипичный график представляет собой комбинацию коробчатого графика и функции плотности вероятности.
  2. Скрипичный график показывает полное распределение данных.
  3. Центральная точка представляет медиану.
sns.violinplot(x=”survival_status_after_5_years”,y =”age”,hue = “survival_status_after_5_years”,data = cancer_df)
plt.title(“Violin plot for survival_status and age”)
plt.show()

График разброса:

Точечная диаграмма представляет собой полезное визуальное представление взаимосвязи между двумя числовыми переменными (атрибутами) и обычно рисуется перед определением линейной корреляции или подгонкой линии регрессии. Полученный шаблон указывает тип (линейный или нелинейный) и силу связи между двумя переменными.

1-D точечный график:

Yes = cancer_df.loc[cancer_df[“survival_status_after_5_years”]==’Yes’]
no = cancer_df.loc[cancer_df[“survival_status_after_5_years”]==’no’]
plt.plot(Yes[“age”],np.zeros_like(Yes[“age”]),’o’,label = “Yes”)
plt.plot(no[“age”],np.zeros_like(no[“age”]),’o’,label = “no”)
plt.title(“1-D scatter plot for age”)
plt.xlabel(“age”)
plt.legend()
plt.show()

Наблюдения:

  1. Посмотрев на этот график, мы можем легко подсчитать количество точек, которые находятся в возрастном диапазоне, кто выжил или нет.
  2. Умерло много людей в возрасте от 41 до 70 лет.

Двухмерный точечный график:

cancer_df.plot(kind = “scatter”,x = “age”, y = “year_of_treatment”)
plt.title(“2-D scatter plot of age”)
plt.show()

Двухмерный график рассеяния с цветовой кодировкой для каждого класса:

sns.set_style(“whitegrid”)
sns.FacetGrid(cancer_df,hue = “survival_status_after_5_years”,size = 4).map(plt.scatter,”age”,”year_of_treatment”).add_legend()
plt.title(“2-D scatter plot for age and year_of_treatement”)
plt.show()

sns.set_style(“whitegrid”)
sns.FacetGrid(cancer_df,hue = “survival_status_after_5_years”,size = 4).map(plt.scatter,”age”,”positive_lymph_nodes”).add_legend()
plt.title(“2-D scatter plot for age and positive_lymph_nodes”)
plt.show()

Наблюдение:

  1. В приведенном выше 2d диаграмме рассеяния метка класса (т.е. человек умер или выжил) не является линейно разделимой.
  2. 0–5 axillary_lymph_node(positive_lymph_nodes) человек выжил и также умер, но коэффициент умерших меньше, чем коэффициент выживших.

Парный сюжет:

  1. Здесь мы создаем парный график на основе выживания_статуса.
  2. Мы используем парный график, где размерность данных меньше.
  3. Мы используем парный график, где размерность данных меньше.
sns.set_style(“whitegrid”)
sns.pairplot(cancer_df,hue = “survival_status_after_5_years”, vars = [“age”,”year_of_treatment”,”positive_lymph_nodes”],size = 3)
plt.suptitle(“pair plot of age,year_of_treatement,azillary_node”)
plt.show()

Наблюдение:

Поскольку мы не можем классифицировать, какая функция является наиболее полезной, из-за слишком большого дублирования. Но, Каким-то образом мы можем сказать, что в год операции умерло еще 60–65 человек, у которых было менее 6 подмышечных_лимфатических_узлов. Следовательно, в данном случае этот сюжет малоинформативен.

Использованная литература:

Для загрузки набора данных: