python进行探索性数据分析EDA(Exploratory Data Analysis)分析

Posted Data+Science+Insight

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python进行探索性数据分析EDA(Exploratory Data Analysis)分析相关的知识,希望对你有一定的参考价值。

python进行探索性数据分析EDA(Exploratory Data Analysis)分析

 

show holy respect to python community, for there dedication and wisdom

 

数据集相关:

第一,UCL wine数据集:

UCI数据集是一个常用的机器学习标准测试数据集,是加州大学欧文分校(University of CaliforniaIrvine)提出的用于机器学习的数据库。机器学习算法的测试大多采用的便是UCI数据集了,其重要之处在于“标准”二字,新编的机器学习程序可以采用UCI数据集进行测试,类似的机器学习算法也可以一较高下。其官网地址如下:
website: UCI Machine Learning Repository
 

字段相关:

固定酸度:大多数与葡萄酒有关的酸或固定的或不挥发的(不易蒸发)
挥发性酸味:葡萄酒中醋酸的含量过高,会产生令人不快的醋味
柠檬酸:少量的柠檬酸可以增加葡萄酒的新鲜度和风味
残糖:发酵结束后的残糖量,每升1克以下的酒很少,45克以上的酒被认为是甜的
氯化物:酒中盐的含量
游离二氧化硫:SO2以游离形式存在于SO2分子(作为溶解气体)与亚硫酸氢盐离子之间的平衡状态;它可以防止葡萄酒中的微生物生长和氧化
总二氧化硫:SO2游离态和结合态的量;在低浓度的情况下,SO2在葡萄酒中几乎检测不到,但当游离SO2浓度超过50ppm时,SO2在葡萄酒的嗅觉和味觉中就会变得明显
密度:根据酒精和糖含量的百分比,水的密度接近于水的密度
pH值:描述葡萄酒的酸性或碱性程度,从0(非常酸)到14(非常碱性);大多数葡萄酒的pH值在3-4之间
硫酸盐:一种葡萄酒添加剂,可以提高二氧化硫气体(SO2)水平,起到抗菌和抗氧化剂的作用
酒精:葡萄酒中酒精含量的百分比
质量:输出变量(根据感官数据,评分0 - 10),有专门的评酒师和调酒师的职业

第二,Kaggle 泰坦尼克号数据集:

泰坦尼克号的沉没是历史上最为人熟知的海难事件之一。 1912 年 4 月 15 日,在她的处女航中,泰坦尼克号在与冰山相撞后沉没,在船上的 2224 名乘客和机组人员中,共造成 1502 人死亡。这场耸人听闻的悲剧震惊了国际社会,从而促进了船舶安全规定的完善。

造成海难失事的原因之一是乘客和机组人员没有足够的救生艇。尽管在沉船事件中幸存下有一些运气因素,但有些人比其他人更容易存活下来,比如女人,孩子和上流社会。

在这个挑战中,要求完成哪些人可能存活下来的分析。特别的,要求运用机器学习工具来预测哪些乘客能够幸免于悲剧。

 

字段相关:

passengerid: 乘客 ID
class: 舱位等级 (1 = 1st, 2 = 2nd, 3 = 3rd)**
name: 乘客姓名
sex: 性别
age: 年龄
sibsp: 在船上的兄弟姐妹/配偶个数
parch: 在船上的父母/小孩个数
ticket: 船票信息
fare: 票价
cabin: 客舱
embarked: 登船港口 (C = Cherbourg, Q = Queenstown, S = Southampton)
survived:  变量预测为值 0 或 1(这里 1 表示幸存,0 表示遇难)

 

 

画图工具相关:

anaconda

Pandas

Numpy

Matplotlib

Seaborn

Bokeh

plotly

# 导入相关包

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

# 绘制标称变量关系图

def plot_categoricals(x, y, data, annotate = True):
    """Plot counts of two categoricals.
    Size is raw count for each grouping.
    Percentages are for a given value of y."""
    # dict vectorizer
    # Raw counts 
    raw_counts = pd.DataFrame(data.groupby(y)[x].value_counts(normalize = False))
    raw_counts = raw_counts.rename(columns = {x: 'raw_count'})
    
    # Calculate counts for each group of x and y
    counts = pd.DataFrame(data.groupby(y)[x].value_counts(normalize = True))
    
    # Rename the column and reset the index
    counts = counts.rename(columns = {x: 'normalized_count'}).reset_index()
    counts['percent'] = 100 * counts['normalized_count']
    
    # Add the raw count
    counts['raw_count'] = list(raw_counts['raw_count'])
    
    plt.figure(figsize = (14, 10))
    # Scatter plot sized by percent
    plt.scatter(counts[x], counts[y], edgecolor = 'k', color = 'lightgreen',
                s = 100 * np.sqrt(counts['raw_count']), marker = 'o',
                alpha = 0.6, linewidth = 1.5)
    
    if annotate:
        # Annotate the plot with text
        for i, row in counts.iterrows():
            # Put text with appropriate offsets
            plt.annotate(xy = (row[x] - (1 / counts[x].nunique()), 
                               row[y] - (0.15 / counts[y].nunique())),
                         color = 'navy',
                         s = f"{round(row['percent'], 1)}%")
        
    # Set tick marks
    plt.yticks(counts[y].unique())
    plt.xticks(counts[x].unique())
    
    # Transform min and max to evenly space in square root domain
    sqr_min = int(np.sqrt(raw_counts['raw_count'].min()))
    sqr_max = int(np.sqrt(raw_counts['raw_count'].max()))
    
    # 5 sizes for legend
    msizes = list(range(sqr_min, sqr_max,
                        int(( sqr_max - sqr_min) / 5)))
    markers = []
    
    # Markers for legend
    for size in msizes:
        markers.append(plt.scatter([], [], s = 100 * size, 
                                   label = f'{int(round(np.square(size) / 100) * 100)}', 
                                   color = 'lightgreen',
                                   alpha = 0.6, edgecolor = 'k', linewidth = 1.5))
        
    # Legend and formatting
    plt.legend(handles = markers, title = 'Counts',
               labelspacing = 3, handletextpad = 2,
               fontsize = 16,
               loc = (1.10, 0.19))
    
    plt.annotate(f'* Size represents raw count while % is for a given y value.',
                 xy = (0, 1), xycoords = 'figure points', size = 10)
    
    # Adjust axes limits
    plt.xlim((counts[x].min() - (6 / counts[x].nunique()), 
              counts[x].max() + (6 / counts[x].nunique())))
    plt.ylim((counts[y].min() - (4 / counts[y].nunique()), 
              counts[y].max() + (4 / counts[y].nunique())))
    plt.grid(None)
    plt.xlabel(f"{x}"); plt.ylabel(f"{y}"); plt.title(f"{y} vs {x}");

# 导入数据并进行查看 

df = pd.read_csv('winequality-white.csv', sep=';')
df.head()
df.tail()
df.sample(5)

 

#检查缺失值的情况:

# Check if any of the following is NULL
df.isnull().any()

#使用热力图查看确实值得程度

sns.heatmap(df.isnull(), cbar=False, yticklabels=False, cmap='viridis')

#查看某些标称变量的独特值得个数、总数等

df.quality.unique()
df.quality.nunique()
df.quality.value_counts()

# 数据类型查看、列名称查看

df.dtypes
df.columns

#获取连续变量的统计信息

df.describe()

#绘制直方图:

df['fixed acidity'].plot(kind = 'hist',figsize=(20, 7), )

#绘制密度图

#绘制箱图

import seaborn as sns
plt.figure(figsize=(10, 7))

sns.boxplot(x=df['alcohol'])

# 绘制箱图,并把图像竖过来

import seaborn as sns
plt.figure(figsize=(10, 7))
sns.boxplot(data = df,y='alcohol',)

# 散点图,scatter plot绘制

import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(16,8))
ax.scatter(df['volatile acidity'] , df['citric acid'])
ax.set_xlabel('volatile acidity')
ax.set_ylabel('citric acid')
plt.show()

#回归图绘制

plt.figure(figsize=(25, 7))
sns.regplot(x="alcohol", y="density", data=df);

#直方图绘制

def bar_plot(df,key):
    df[key].value_counts().sort_index().plot.bar(figsize = (12, 5),
                      edgecolor = 'k', linewidth = 2)

    # Formatting
    plt.xlabel(key); 
    plt.ylabel('COUNT'); 
    plt.xticks(rotation = 60)
    plt.title('BAR PLOT for ' + key);
    plt.show()


bar_plot(df,'quality')

#多箱图绘制

def plot_box_plot2(df,key,value):
    import copy
    box = copy.deepcopy(df)
    box[value] = box[value].astype('float')
    sns.set_style('whitegrid',{'font.sans-serif':['SimHei','Arial']})
    sns.set_context("talk")
    fig,axes=plt.subplots(1,1,figsize = (25,7))
    sns.boxplot(data = box, x=key, y=value)
    plt.show()

plot_box_plot2(df,'quality','citric acid')

plt.figure(figsize=(25, 7))
# plt.style.use('seaborn-white')
ax = sns.boxplot(x="quality", y="free sulfur dioxide", data=df)

#绘制小提琴图 

plt.figure(figsize=(25, 7))
sns.set_theme(style="whitegrid")

# Draw a nested violinplot and split the violins for easier comparison
sns.violinplot(data=df, x="quality", y="density", 
               split=True, inner="quart", linewidth=1,)
sns.despine(left=True)

 

#绘制相关性图:

plt.figure(figsize=(15,8))
sns.heatmap(df.corr(),cmap='Greens',annot=False)

#绘制相关性图,并显示相关性数值

plt.figure(figsize=(15,15))
sns.heatmap(df.corr(), color='b', annot=True)

# 绘制标称变量的统计图

plt.figure(figsize=(15,5))
sns.countplot(x='quality', data = df)

# 绘制所有变量的箱型图:

plt.figure(figsize=(10,15))

for i, col in enumerate(list(df.columns.values)):
    plt.subplot(4,3,i+1)
    df.boxplot(col)
    plt.grid()
    plt.tight_layout()

#绘制所有变量的直方图

plt.figure(figsize=(20,16))

for i,col in enumerate(list(df.columns.values)):
    plt.subplot(4,3,i+1)
    sns.distplot(df[col], color='b', kde=True, label='data')
    plt.grid()
    plt.tight_layout() 

# pair plot

sns.pairplot(data=df, kind='scatter',diag_kind='kde')

 

# 把变量离散化并构建离散变量关系图

df['alcohol_bin'] = pd.cut(df.alcohol,bins=[7,9,11,13,15],labels=['low','mid_low','mid_high','high'])
# df.insert(5,'Age Group',category)

df['alcohol_value'] = pd.cut(df.alcohol,bins=[7,9,11,13,15],labels=[1,2,3,4])
# df.insert(5,'Age Group',category)


plot_categoricals('alcohol_value', 'quality', df, annotate = True)

 

 

# 泰坦尼克号数据集

 

#加载数据

df=pd.read_excel(titanic.xls")

df.head()

# df.tail()

#df.sample(5)

#df.columns

#df.shape

#df.info()

#获取统计信息

df.describe()

# describe默认只输出连续变量的信息,那么我想看其他变量类型的数据的统计信息:

df.describe(include=[bool,object])

#查看统计信息(单列)

df.fare.mean()

df[df['survived']==1].mean()

df[(df['survived'] == 1) & (df['pclass'] == 1)]['age'].max()

df[df['name'].apply(lambda name: name[0] == 'A')].head()

 

df[df['name'].apply(lambda name: name[0] == 'A')].head()

# replace函数:

x = {1 : 'Class I', 2 : 'Class II', 3:'Class III'}
df_new=df.replace({'pclass': x})
df_new.head()

# 获取聚合信息(groupby)

# 列联表信息

pd.crosstab(df['survived'], df['pclass'])
pd.crosstab(df['survived'], df['sex'], margins=True)

#透视表pivot

df.pivot_table(['fare','age'],['survived'],aggfunc='mean')
df.pivot_table(['fare','age'],['survived'],aggfunc='median')

#数据排序(基于某个特定字段)

df.sort_values(by=["fare"], ascending=False).head()
df.sort_values(by=["fare"], ascending=False).tail()

#缺失值情况可视化

import seaborn as sns
plt.rcParams['figure.dpi'] = 100# the dpi can be set to enhance the resolution of the image
# Congiguring retina format
%config InlineBackend.figure_format = 'retina'
sns.heatmap(df.isnull(), cmap='viridis',yticklabels=False)

#生存情况统计

sns.countplot(x=df.survived)

#不同性别的生存情况

sns.countplot(data =df, x = 'survived',hue = 'sex')

#舱位登记不同生存统计

sns.countplot(data = df , x = 'survived', hue='pclass')

#舱位等级和生存的交叉表

pd.crosstab(df['survived'], df['pclass'], margins=True)

#舱位计数统计

sns.countplot(df.pclass)

# 绘制年龄直方图、密度图

plt.figure(figsize=(20, 7))
sns.distplot(df.age, color='purple')

# 绘制年龄直方图、密度图(去除缺失值)

plt.figure(figsize=(20, 7))
sns.distplot(df['age'].dropna(),color='darkred',bins=40)

#费用的密度图

plt.figure(figsize=(20, 7))
sns.distplot(df.fare, color='green')

#绘制费用的箱图和小提琴图:

plt.figure(figsize=(20, 7))

plt.subplot(1,2,1)
sns.boxplot(data = df, y='fare',orient = 'v')
plt.subplot(1,2,2)
sns.violinplot(data = df, y='fare',orient = 'v')
#(Q1−1.5⋅IQR, Q3+1.5⋅IQR) 

#费用和年龄相对于舱位等级的箱图

plt.figure(figsize=(20, 7))

plt.subplot(1,2,1)
sns.boxplot(x=df.pclass,y=df.fare)
plt.subplot(1,2,2)
sns.boxplot(x=df.pclass, y=df.age)

#相关性可视化

# Considering only numerical variables
scatter_var = list(set(df.columns)-set(['name', 'survived', 'ticket','cabin','embarked','sex','sibsp','parch']))

# Creating heatmap
corr_matrix = df[scatter_var].corr()
sns.heatmap(corr_matrix,annot=True);

#年龄和费用的散点图

plt.scatter(df['age'], df['fare'])
plt.title("Age Vs Fare")
plt.xlabel('Age')
plt.ylabel('Fare')

# 舱位等级和费用的散点图

plt.scatter(df['pclass'], df['fare'])
plt.title("pclass Vs fare")
plt.xlabel('pclass')
plt.ylabel('fare')

# pair plot of variables

#两两变量之间的散点关系

sns.pairplot(df[scatter_var])

# 性别、登船地点、舱位等级生存统计信息

f, [ax1,ax2,ax3] = plt.subplots(1,3,figsize=(20,5))
sns.countplot(x='sex', hue='survived', data=df, ax=ax1)
sns.countplot(x='pclass', hue='survived', data=df, ax=ax2)
sns.countplot(x='embarked', hue='survived', data=df, ax=ax3)
ax1.set_title('sex feature analysis')
ax2.set_title('pclass feature analysis')
ax3.set_title('embarked feature analysis')
f.suptitle('categorical feature analysis', size=20, y=1.1)

plt.show()

#登船地、舱位等级、性别交叉统计图

grid = sns.FacetGrid(data = df, col='pclass', hue='sex', palette='seismic', size=4)
grid.map(sns.countplot, 'embarked', alpha=0.8)
grid.add_legend()

#绘制生存与否的年龄密度图:

f,ax = plt.subplots(figsize=(10,5))
sns.kdeplot(df.loc[(df['survived'] == 0),'age'] , color='gray',shade=True,label='not survived')
sns.kdeplot(df.loc[(df['survived'] == 1),'age'] , color='g',shade=True, label='survived')
plt.title('age feature distribution', fontsize = 15)
plt.xlabel("age", fontsize = 15)
plt.ylabel('frequency', fontsize = 15)

# 不同性别、生存情况下的年龄密度图:

def plot_distribution( df , var , target , **kwargs ):
    row = kwargs.get( 'row' , None )
    col = kwargs.get( 'col' , None )
    facet = sns.FacetGrid( df , hue=target , aspect=4 , row = row , col = col )
    facet.map( sns.kdeplot , var , shade= True )
    facet.set( xlim=( 0 , df[ var ].max() ) )
    facet.add_legend()


plot_distribution( df , var = 'age' , target = 'survived' , row = 'sex' )

# 不同生存情况人群的费用图

以及计算方差和均值并进行可视化分析

# 填充缺失值
df["fare"].fillna(df["fare"].median(), inplace=True)

df['fare'] = df['fare'].astype(int)

# 分别获得生还和遇难乘客的 Fare
fare_not_survived = df["fare"][df["survived"] == 0]
fare_survived = df["fare"][df["survived"] == 1]

# 得到 Fare 的均值和方差
avgerage_fare = pd.DataFrame([fare_not_survived.mean(), fare_survived.mean()])
std_fare = pd.DataFrame([fare_not_survived.std(), fare_survived.std()])

df['fare'].plot(kind='hist', figsize=(15,3),bins=100, xlim=(0,50))

avgerage_fare.index.names = std_fare.index.names = ["survived"]
avgerage_fare.plot(yerr=std_fare,kind='bar',legend=False)

# 孤独以及和家庭一起出发的统计

# 孤独一个人还是和家庭一起,对生存的影响


df['family'] =  df["parch"] + df["sibsp"]
df['family'].loc[df['family'] > 0] = 1
df['family'].loc[df['family'] == 0] = 0


# 删除 Parch 和 SibSp
df_new = df.drop(['sibsp','parch'], axis=1)

# 绘图
fig, (axis1,axis2) = plt.subplots(1,2,sharex=True,figsize=(10,5))

sns.countplot(x='family', data=df, order=[1,0], ax=axis1)

# 分为和家人一起、独自乘船两种情况
family_perc = df_new[["family", "survived"]].groupby(['family'],as_index=False).mean()
sns.barplot(x='family', y='survived', data=family_perc, order=[1,0], ax=axis2)

axis1.set_xticklabels(["With Family","Alone"], rotation=0)

# pair plot

g = sns.pairplot(df[[u'survived', u'pclass', u'sex', u'age', u'family', u'fare', u'embarked']], hue='survived', palette = 'seismic',
                 size=4,diag_kind = 'kde',diag_kws=dict(shade=True),plot_kws=dict(s=50) )
g.set(xticklabels=[])

# pandas profiling

#pip install pandas-profiling

# from pandas_profiling import ProfileReport
# EDA_report = ProfileReport(df)
# EDA_report.to_file(output_file='EDA.html')

参考:kaggle

参考:Interview Questions on Exploratory Data Analysis (EDA)

参考:Introduction to Exploratory Data Analysis (EDA)

参考:How to do Exploratory Data Analysis (EDA) with python?

参考:Kaggle入门级赛题:泰坦尼克号生还者预测——数据分析篇

参考:Kaggle入门级赛题:泰坦尼克号生还者预测——数据挖掘篇

参考:UCI数据集整理(附论文常用数据集)

参考:pandas

参考:pandas profiling

 

以上是关于python进行探索性数据分析EDA(Exploratory Data Analysis)分析的主要内容,如果未能解决你的问题,请参考以下文章

Python数据分析(八):农粮组织数据集探索性分析(EDA)

手把手教学:使用Elastic search和Kibana进行数据探索(Python语言)

YYDS!几行Python代码,就实现了全面自动探索性数据分析

YYDS!几行Python代码,就实现了全面自动探索性数据分析

数据分析可视化利器:python pandas-profiling 一行代码EDA 探索性数据分析

区区几行代码,就能全面实现 Python 自动探索性数据分析