2

Pandas 探索性数据分析综合实战

 1 year ago
source link: https://www.51cto.com/article/722544.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Pandas 探索性数据分析综合实战

作者:云朵君 2022-11-11 11:35:14
本文的内容是关于对数据集进行特别分析,并试图找到关于数据的洞察力。我们做了处理缺失值、异常值的工作,并将单变量、双变量和多变量的分析可视化。

​本文主要分析数据、组织数据、清洗、过滤、排序、聚合、可视化变量之间的关系、分类图和数据的分散性。在一个数据科学项目的生命周期中,我们有70%以上的时间用于数据分析,比如进行特征工程和特征选择。特征工程讲的是根据我们的直觉用有效的数据来填补缺失值,纠正错误的数据类型,组织不平衡的数据集,而特征选择讲的是只选择那些有助于预测变量或你感兴趣的输出的特征。要做好探索性数据分析,需要对pandas、numpy、scipy、matplotlib和seaborn库有很好的了解。

本文的目的是了解数据集的要点,即对数据的初步了解。当你收到一个数据集时,你需要对数据集的变量、数据类型和变量之间的关系有一个概念。在大多数情况下,我们会在数据集中发现不完整的数据,原因可能是用户可能不想填写数据,在互联网上传输时数据丢失,或者用户可能没有数据可以填写。这是需要解决的第一步。不匹配的数据类型,如DateTime变量一般被读成对象(String),或者有时整数被读成浮点数,反之亦然。在本文中,我们将使用一个实时的泰坦尼克号数据集,并对其进行探索性数据分析。

导入库和数据集

开始导入所需的库pandas、numpy、seaborn、matplotlib、魔法命令%matplotlib inline,并使用 read_csv 方法加载titanic数据集(titanic.csv),如图所示。

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

%matplotlib inline

现在我们可以开始对数据框架做一些初步的检查,比如读取几行几列以确保数据被加载到数据框架中,找到它的形状(行数和列数),数据类型的信息。

我们可以使用head方法查看前几行,如图所示。这个方法需要一个整数作为参数,并返回总的行数。

图片

我们可以通过shape​属性知道数据集的大小,如行和列的总数,如下所示,该属性显示一个有891行和12列的元组。为了找到变量的数据类型,我们有info方法,它可以返回变量、数据类型、内存使用量和关于每个变量的缺失值,Age​只有714,Cabin只有 204,不是891,因此他们需要被填充,在接下来我们对其进行可视化并处理缺失值。

df.shape
(891, 12)
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
PassengerId    891 non-null int64
Survived       891 non-null int64
Pclass         891 non-null int64
Name           891 non-null object
Sex            891 non-null object
Age            714 non-null float64
SibSp          891 non-null int64
Parch          891 non-null int64
Ticket         891 non-null object
Fare           891 non-null float64
Cabin          204 non-null object
Embarked       889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.6+ KB

处理缺失值

我们可以使用missingno​库对数据集进行可视化处理,也可以使用isnull​方法检查 "Age"​ 和 "Cabin" 两列中缺失的数值。

df.isnull().sum()
PassengerId      0
Survived         0
Pclass           0
Name             0
Sex              0
Age            177
SibSp            0
Parch            0
Ticket           0
Fare             0
Cabin          687
Embarked         2
dtype: int64

我们可以看到 'Age'​ 列有177个空值,'Cabin' 有687个空值,下面的图是整个数据集的可视化图。

图片

现在来处理缺失的 "Age"​ 值,"Age"​ 的数据类型是数字(Float),一般来说,缺失的数字列会用它们的平均值或中位数或任何基于我们直觉的值来填补,无论哪种都是最好的。在更新空值之前,检查一下基于 "Pclass"​ 和 "Sex"​ 列的均值和中值。下图显示了基于 "Pclass"​ 和 "Sex" 分组的平均数和中位数。这里我们可以看到平均数和中位数都非常接近,所以更好的选择是继续使用中位数。

df.groupby(["Pclass", "Sex"])["Age"].mean()
Pclass  Sex   
1       female    34.611765
        male      41.281386
2       female    28.722973
        male      30.740707
3       female    21.750000
        male      26.507589
Name: Age, dtype: float64
df.groupby(["Pclass", "Sex"])["Age"].median()
Pclass  Sex   
1       female    35.0
        male      40.0
2       female    28.0
        male      30.0
3       female    21.5
        male      25.0
Name: Age, dtype: float64

所以根据'Pclass'和'Sex'​,我们可以更新'Age'​变量的空值。这里我们可以使用loc​方法来寻找和替换'Age'变量的空值。

# Fillin the age values for  Pclass =1 for male  and  Female
df.loc[df.Age.isnull() & (df.Sex == "male") & (df.Pclass == 1), "Age"] = 37
df.loc[df.Age.isnull() & (df.Sex == "female") & (df.Pclass == 1), "Age"] = 35.5

# Fillin the age values for  Pclass =2 for male  and  Female
df.loc[df.Age.isnull() & (df.Sex == "male") & (df.Pclass == 2), "Age"] = 29.0
df.loc[df.Age.isnull() & (df.Sex == "female") & (df.Pclass == 2), "Age"] = 28.5

# Fillin the age values for  Pclass =2 for male  and  Female
df.loc[df.Age.isnull() & (df.Sex == "male") & (df.Pclass == 3), "Age"] = 25
df.loc[df.Age.isnull() & (df.Sex == "female") & (df.Pclass == 3), "Age"] = 22

现在我们已经填补了'Age'​变量的缺失值,那么'Cabin'​变量呢,它只是船上的一个座位分配,这个变量对乘客的生存没有任何影响,所以我们可以使用drop​方法放弃这个变量。再次绘图并检查是否有遗漏值。现在可以看到'Age'列没有任何空值,如下图所示,甚至'Cabin'列也被删除了:

df.drop(columns="Cabin", inplace=True)
ms.bar(df, color="orange", inline=True)
图片

数据处理部分已经完成。现在可以利用这些干净的数据,对其进行分析。在进一步进行之前,了解每一列所代表的内容。下面描述了每一列含义,这些字段很简单,不言自明。

PassengerId:只是一个序列号

Survived: 0 = No, 1 = Yes

pclass: Ticket class 1 = 1st, 2 = 2nd, 3 = 3rd

sibsp: # 在泰坦尼克号上的兄弟姐妹/配偶的数量

parch: # 泰坦尼克号上的父母/子女的数量

ticket: Ticket number

cabin: Cabin number

embarked: Port of Embarkation C = Cherbourg, Q = Queenstown, S = Southampton

现在我们对数据集有了一个概念,但我们想从数据集中定义的问题陈述是什么?它可以是像幸存的总人数或他们旅行的班级,或有多少人有兄弟姐妹或配偶,父母-子女,等等。接下来用seaborn来绘图。

仅仅重申我们在统计学章节中讨论过的内容,我们有两种变量分类和数字,这些变量又进一步细分为序数和名义,以及数字变量的连续和离散,如图所示。

图片

分类名义变量

顺序变量的定义与分类变量类似;这里需要提到的是,它没有任何特定的顺序。一个例子是我们不能在这里假设男性大于女性。我们不能假设一个类别大于或小于其他类别,而且它们没有任何特定的顺序。

分类顺序变量

分类的、序数的变量可以按特定的顺序排列。一个例子是,如果你被要求填写餐厅的食物和服务的反馈,这可能是诸如美味、好、更好、更差和最差。这有一个从正到负的特定顺序,或者另一个例子是指一个班级的成绩。

数值连续变量

数字连续变量有无限的值。这方面的例子可以是股票价格、身高、体重、年龄,等等。这些值没有任何有限的区间。

数值离散变量

数值离散型变量有有限的值。一个例子是你有多少辆汽车或你有多少个孩子。它有一个确定的值,要么是0,1,2,等等。我们不可能有1.24辆汽车或1.05个孩子。

在泰坦尼克号数据集中有哪些不同的变量,并直观地看到它们的数据类型表示。我们可以看到这些变量的单独表示。

Name:分类名义变量。

Surviver:分类名义变量。

Pclass:分类顺序变量。

Sex:分类名义变量。

Embark:分类名义变量。

Age:数值连续变量。

SibSp:数值离散变量。

Parch:数值离散变量。

Fare:数值连续变量。

单变量分析

单变量分析是关于一个单一的变量。使用seaborn,我们可以将一些最重要的图示可视化。我们把船上幸存的乘客总数可视化。可以使用计数图的方法,如图所示。我们可以看到891人中只有350多人幸存下来。

sns.countplot(x="Survived", data=df)
图片

"Embarked"变量是分类类型的,它表示在不同港口上船的人数。我们可以用countplot方法绘制,如下图所示。

sns.set_style("whitegrid")
sns.countplot(x="Embarked", data=df)
图片

另一个分类变量是Sex(性别);我们也可以绘制它,如下图所示。

sns.countplot(x="Sex", data=df)
图片

我们也可以对数字变量使用countplot​方法。我们可以绘制'SibSp'(配偶和兄弟姐妹)变量,如图所示,它显示600人是单独旅行,200人以上有1个兄弟姐妹或配偶,以此类推。

sns.countplot(x="SibSp", data=df)
图片

双变量分析

到现在为止,我们已经学习了单变量的分析,称为单变量分析,而双变量分析是用来寻找两个变量之间的关系。为此寻找'Fare'和'Age'​变量之间的关系,我们可以使用relplot方法,如图所示。

sns.set_style("darkgrid")
g = sns.relplot("Age", "Fare", data=df)
g.fig.set_figwidth(12)
g.fig.set_figheight(6)
图片

我们可以看到年龄范围从0到80,大部分票价都落在0到100的范围内,同时,38岁的人有一个500以上的票价的离群值。很少有变量落在200到300的范围内。不同的双变量图是散点图、热图、线图和柱状图。

散点图是统计可视化的骨干。它用一团数据点描述了两个变量之间的联合分布。这一点我们已经在上图中比较了 "Fare"​和 "Age"的例子。

在seaborn中,线状图可以通过relplot​方法完成,通过设置参数kind='line',如下图所示。

sns.relplot("Age", "Fare", kind="line", data=df)
图片

使用热图法,我们可以用二维的形式来表示数据。数据值在图中被表示为颜色,同时还有变量之间的数字相关性。在这里使用泰坦尼克号数据集,我们试图表示变量之间是否有任何相关性。下图显示,这些变量之间没有太大的相关性,而且它们是相互独立的。

corr = df.corr()
sns.heatmap(corr, annot=True)
图片

柱状图是最常见的一种图表类型。它显示了数字变量和分类变量之间的关系,如图所示。从图中我们可以看出,第1类乘客的生存率更高。

sns.barplot(x="Pclass", y="Survived", data=df, ci=None)
图片

多变量分析

多变量分析同时使用两个以上的变量。通常我们可以看到,更多的变量可以是多维的,如下图所示。这里我们将性别及他们的存活率与他们所乘坐的客运等级一起绘制出来。我们可以看到,与男性相比,女性乘客的存活率更高,而且Pclass ​1和Pclass 2的存活率也更高。

sns.barplot(x="Sex", y="Survived", hue="Pclass", data=df, ci=None)
图片

我们还可以画一个散点图来表示多变量分析,如下图所示,它显示了"Age"和 "Fare"​以及他们的 "Survived"​。这里我们可以描述出,与低票价相比,高票价的人存活率更高,也就是说,Pclass 1和Pclass 2比Pclass 3存活率更高。有时单变量和双变量分析并不能提供太多的信息,所以这里我们可以使用多变量分析。

sns.relplot(x="Age", y="Fare", hue="Survived", data=df)
图片

处理离群点

离群点大多可能是数据中的一个错误,如打字错误、季节性趋势等。在这种情况下,在计算汇总统计或从数据中得出见解之前,应该将其从数据集中纠正或删除,否则会导致不正确的分析。假设你有一个美国不同州的披萨价格数据集,如下图所示。

图片

我们可以计算变量的长度,也可以用箱形图直观地看到异常值,如下图所示。

sns.boxplot("price", data=df)
图片

我们可以看到我们有3个离群点。现在如果我们计算价格的平均值,我们得到的数值是35.12。

由于存在离群点,我们可以把它们丢掉,如下所示,再次计算平均值,这里我们可以看到平均值是16.67,几乎是有离群点的数值的一半。所以在数据分析过程中,去除离群值是很重要的。

df.drop(df[df.price == 160.32].index, inplace=True)
df.drop(df[df.price == 63.43].index, inplace=True)
df.drop(df[df.price == 158.38].index, inplace=True)

在特征选择中,我们在那些对使用机器学习进行预测很重要的变量上下功夫。一些特征,如'Passengerid'、'Name'、'Cabin' 和 'Ticket'在进行分析时不会产生任何影响,因此在使用机器学习算法进行任何预测之前,最好放弃这些变量。

还是使用泰坦尼克号数据集并对其进行特征选择,如下图所示。

图片

我们可以使用删除法,删除 "Passengerid"、"Name"、"Cabin "和 "Ticket "这几列,如下图所示。

图片

在上图中,我们可以看到这些列被删除了,很好,但是这里有一个问题。ML算法只理解数字,但是我们这里有两个类别列'Sex'和'Embarked'​,它们是对象(字符串)类型。性别列有男性和女性两个类别,而对于Embarked,我们有S、C和Q值。

df_main["Sex"].value_counts()
male      577
female    314
Name: Sex, dtype: int64
df_main["Embarked"].value_counts()
S    644
C    168
Q     77
Name: Embarked, dtype: int64

我们更新 S、Q 和 C 的性别栏0、1(男性和女性)和 0、1、2(登船)的值。

df_main.loc[df_main["Sex"] == "male", "Sex"] = 1
df_main.loc[df_main["Sex"] == "female", "Sex"] = 0
df_main.loc[df_main["Embarked"] == "S", "Embarked"] = 0
df_main.loc[df_main["Embarked"] == "Q", "Embarked"] = 1
df_main.loc[df_main["Embarked"] == "C", "Embarked"] = 2
df_main.head()
图片

现在我们可以将数据集的信息特征和目标进行划分。X​变量就像一个带有行和列的矩阵,称为特征,而y变量是目标。

X = df_main.drop(columns="Survived")
X.head()

因此,我们可以结束特征选择部分,进一步将特征分为train_test_split,并应用适当的机器学习算法,进行预测。

图片

本文的内容是关于对数据集进行特别分析,并试图找到关于数据的洞察力。我们做了处理缺失值、异常值的工作,并将单变量、双变量和多变量的分析可视化。探索性数据分析是数据分析中最核心和最重要的概念之一。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK