Last chance! 50% off DataCamp Premium
Sale ends in
按数据科学主题探索内容
按工具和技术探索内容
如您现在所知,Python 的数据处理库 Pandas 用于数据操作;对于刚入门的读者,这可能意味着该软件包只能在预处理数据时派上用场,但事实远非如此:Pandas 同样非常适合探索数据,并在预处理完成后保存数据。
此外,对于一直在学习 DataCamp Python 教程或已接触过 SciPy、NumPy、Matplotlib 和 Pandas 基础的读者,回顾一下您已掌握的部分知识也是个不错的主意。
本教程将向您介绍如何结合上述各个包高效地探索数据,以便开始对数据进行建模:
有兴趣学习一门 Pandas 课程吗?不妨考虑我们的使用 pandas 进行数据操作课程!
要开始探索数据,首先需要真正把数据加载进来。您或许已经知道,借助 Pandas 库,这变得很简单:按惯例以 pd 导入该包,然后使用 read_csv() 函数,将包含数据的 URL 和一个 header 参数传入。后一个参数可用于确保正确读取数据:数据的第一行不会被解释为 DataFrame 的列名。
pd
read_csv()
header
此外,您还可以指定其他参数来确保数据被正确读取:例如用 sep 或 delimiter 指定分隔符,用 names 指定列名,或用 index_col 指定作为结果 DataFrame 行标签的列。
sep
delimiter
names
index_col
当然,这些远不是 read_csv() 可用的全部参数。请在文档中了解该函数及其参数。
请注意,在此示例中使用 read_csv() 是因为数据恰好采用逗号分隔格式。如果您的文件使用其他分隔符,也可以考虑使用其他函数加载数据,如 read_table()、read_excel()、read_fwf() 和 read_clipboard,分别用于读取通用定界文件、Excel 文件、定宽格式数据以及剪贴板中的数据。
read_table()
read_excel()
read_fwf()
read_clipboard
另外,您还可以使用 read_sql() 将 SQL 查询或数据库表读入 DataFrame。更多输入函数请参阅 Pandas 文档此部分。
read_sql()
探索性数据分析(EDA)一方面用于回答问题、检验业务假设、为进一步分析生成假设;另一方面,您也可以用它来为建模做准备。这两者的共同点很可能在于:对数据有充分了解,以便获得所需答案,或培养对未来建模结果的解释直觉。
达成这些目标的方法很多:您可以获取数据的基本描述、进行可视化、识别其中的模式、识别使用数据的挑战等。
在阅读 EDA 相关内容时,您经常会看到“数据剖析”(Data profiling)。数据剖析关注通过描述性统计对数据集进行汇总。您希望使用多种度量来更好地理解数据集。数据剖析的目标是对数据有扎实的理解,从而随后能够以多种方式开始查询和可视化数据。但这并不意味着您不需要迭代:正因为数据剖析旨在总结数据集,它也常用于评估数据质量。根据剖析结果,您可能会决定纠正、丢弃或以不同方式处理数据。
关于数据剖析的更多内容,您将在下一篇文章中学习。
尽管二者关系密切,且许多 EDA 技术已被数据挖掘采纳,但 EDA 仍有别于数据挖掘。两者的目标也非常相似:EDA 确保您以一种方式探索数据,使有趣的特征及特征之间的关系更加清晰。在 EDA 中,您通常会用多种技术探索并比较许多不同变量,以搜寻并发现系统性模式。而数据挖掘则侧重于从数据中提取模式。这些模式能够提供变量间关系的洞见,可用于改进业务决策。此外,在两种情况下,您对于变量间关系通常没有先验期望,或期望并不完整。
然而,一般而言,数据挖掘更偏向应用导向,而 EDA 更关注潜在现象的基本本质。换言之,数据挖掘对识别所涉变量之间的具体关系关注相对较少。因此,数据挖掘接受一种“黑箱”式的数据探索方法,既使用 EDA 中的技术,也使用诸如神经网络等技术来生成有效预测,但并不识别预测所依据的变量关系的具体性质。
如上所述,EDA 的核心是熟悉您的数据。实现这一点最基础的步骤之一,就是获取数据的基本描述。对数据的“基本描述”确实是一个非常宽泛的说法:您可以将其理解为快速获取一些关于数据的信息、以简单易懂的方式了解数据、建立对数据的基本感觉等。
本节不对这些理解做区分:它将介绍一些方法,帮助您快速收集易于理解的 DataFrame 信息。
例如,您可以使用 describe() 函数来获取各种不包含 NaN 值的汇总统计。请看下面这个对著名的 Iris 数据集进行描述的示例。数据已在 DataCamp Light 代码块中为您加载:
describe()
您会看到,该函数返回计数、均值、标准差、最小值与最大值以及分位数。需要注意的是,当然,Python 中有许多包(包括 Pandas 本身)可以给出这些统计量。使用该函数只是获取这些信息的方式之一。
同样需要注意的是,如果尚未深入了解描述性统计,务必花时间补上。您可以用这些统计量开始评估数据质量,进而决定是要纠正、丢弃,还是以其他方式处理数据。这通常就是“数据剖析”步骤。EDA 中的该步骤旨在更好地理解数据元素及其异常,并查看数据一方面与文档的匹配情况,另一方面能否满足业务需求。
注意 随着探索性数据分析的推进,您会回到数据剖析步骤,因为您执行的各个步骤可能会影响数据质量。
在对数据集有了总体印象后,更近一步查看数据本身也是个好主意。借助 Pandas 的 head() 和 tail() 函数,您可以轻松分别查看 DataFrame 的前几行与后几行。
head()
tail()
在下方的 DataCamp Light 代码块中,使用 head() 和 tail() 检查手写数字数据的前五行和后五行。数据已为您加载:
当您不熟悉这类数据时,会发现 head() 和 tail() 的结果并不能说明太多。
您可能只看到一堆包含数值的行和列。如果尚未阅读,建议查看该数据集说明,它将提供有关数据如何收集的相关信息,还会给出属性和行数,这有助于检查您是否正确导入了数据。
另外,回到最初的发现:行中的数值。乍一看,您可能觉得没有问题,因为整数看起来正确,初看并未引发任何警示。
但如果将这些步骤用于另一个数据集,而那个数据集中包含了例如日期时间信息,那么快速浏览这些代码行的结果时,可能会产生如下问题:“我的数据是否被读取为 DateTime?”,“我该如何检查?”以及“怎样更改数据类型?”。
这些都是您通常会在数据剖析步骤中解决的更深入的问题,我们将在下一篇文章中讨论。
如果数据集很大,您可以考虑对数据进行抽样,以便快速建立对数据的感知。最简单的方式是使用 Pandas 中的 sample() 函数,如下所示:
sample()
另一种——或许更复杂——的方法是创建一个随机索引,然后从 DataFrame 中随机获取行。您会看到下面的代码使用了 random 包中的 sample 模块配合 range() 和 len() 来对数据进行抽样。注意,您还使用了 ix 来选择样本中需要包含的 DataFrame 精确行。
random
sample
range()
len()
ix
如果您不清楚为何在此场景下使用 ix,DataCamp 更具体的教程可以帮到您!它详细介绍了这些更通用的话题。点击上面的链接了解更多!
现在,让我们练习一下 Python 技能!从下面的练习开始:
现在您已粗略浏览过数据,并了解它的大致内容,可以更进一步:是时候通过查询来深入检查数据了。
这在 query() 函数的帮助下非常容易,它允许您测试一些关于数据的非常简单的假设,例如“花瓣长度通常是否大于花萼长度?”或“花瓣长度是否有时等于花萼长度?”。
query()
您会看到,这个假设并不成立。结果返回的是一个空的 DataFrame。
注意 该函数也可以写作 iris[iris.Petal_length > iris.Sepal_length]。
iris[iris.Petal_length > iris.Sepal_length]
在收集了一些基础信息后,进一步了解数据可能带来的挑战是个好主意。如果您已经完成数据剖析步骤,应该会意识到缺失值的存在,也能大致识别哪些值可能是离群值等。
本节将介绍一些基础方法,帮助您先对这些问题有个初步认识,并说明在发现数据中出现不规则情况时如何处理。再次注意,您将会或已经在数据剖析步骤中更深入地识别这些不规则情况,而且在处理完某些挑战后返回该步骤也是很正常的。
在探索数据时,您可能也想检查数据集中是否存在缺失值。
检查这一点很重要,因为当部分数据缺失时,数据集的表达力会下降,可能导致分析变弱或产生偏差。具体而言,这意味着当某些特征存在缺失值时,数据分类或预测出现偏差的可能性会增加。
当然,数据集中出现缺失的原因,可能是数据提取或导入出错,也可能是数据采集过程造成的。为您提供数据的系统可能出现故障,或者您发出的问卷有受访者留空。还应认真考虑缺失数据是否存在某种模式,这正是数据剖析能发挥作用的地方。记住,您可以通过数据剖析更好地了解数据质量。在后续文章中,您可以阅读更多关于如何发现缺失数据模式的内容。
简而言之,缺失数据的成因多种多样,很大程度上取决于数据语境,也可能取决于您自身的处理。因此,您在前面的步骤中导入数据后首先检查数据就是为了这个目的!
要识别包含缺失值的行,您可以使用 isnull()。返回结果的每个单元格中都会出现 True 或 False:True 表示该单元格内的值是缺失值,False 表示该单元格包含“正常”值。
isnull()
True
False
在本例中,数据相当完整:没有缺失值。
注意 您也可以在上文链接的 UCI 机器学习资源库的数据集描述中看到这一点,其中注明了该数据没有缺失值。
不过,并非所有数据集都如此。这就是为什么当您遇到需要考虑如何处理缺失数据的情况时,知道可以做些什么很重要。
请注意,上述每种方式都有各自的优缺点!在做最终决定前,您需要综合考虑时间、成本、数据性质等因素。
一旦决定如何处理缺失数据,继续阅读,了解如何在数据中实现您想要的更改。
如果您决定使用插补来填充值,仍然可以选择实现方式!
结合使用 Pandas 的 fillna() 与 NumPy 提供的函数。考虑以下代码段:假设您有一个调查结果的 DataFrame,调查内容为受访者的薪资。在一个所有受众都来自同一社会阶层且受访者回答该问题的概率对每个人都相同的语境中,您可以选择计算已回答人群的平均值,并用该平均值填补未回答者的值。
fillna()
# Import NumPyimport numpy as np# Calculate the meanmean = np.mean(df.Salary)# Replace missing values with the meandf. = df.Salary.fillna(mean)
当然,您不一定要向 fillna() 传入具体数值。也可以通过为 fillna() 加上 method 参数来向前或向后传播非空值。传入 ffill 或 bfill 指定向后或向前填充。
method
ffill
bfill
要排除包含缺失值的列或行,可以使用 Pandas 的 dropna() 函数:
dropna()
# Drop rows with missing valuesdf.dropna(axis=0)# Drop columns with missing values df.dropna(axis=1)
或者,您也可以选择对缺失值进行插值:interpolate() 会在缺失点进行线性插值,以“猜测”最可能填入的值。
interpolate()
df.interpolate()
您还可以添加 method 参数来使用更高级的插值方法,比如多项式插值或三次插值,但若要使用这些插值类型,您需要安装 SciPy。
当然,插值也有其局限性,尤其当用于插值的 NaN 值与上一个有效观测相距过远时。在这种情况下,您可以在原始代码中添加 limit 参数。传入一个正整数,该数将决定在非 NaN 值之后有多少个值会被填充。默认的限制方向是向前,您也可以通过添加 limit_direction 来修改。
limit
limit_direction
与缺失值类似,数据中也可能包含与大多数其他数据大相径庭的值。这些数据点称为“离群值”。要找到它们,您可以通过箱线图检查单个变量的分布,或绘制散点图来识别不在图上“预期”区域内的数据点。
数据中出现离群值的原因可能各不相同,从系统错误到人为在数据录入或处理中的干预不等,但重要的是要考虑它们对分析的影响:它们会改变诸如标准差、均值或中位数等统计检验的结果,可能降低正态性,并影响回归或方差分析(ANOVA)等统计模型的结果。
处理离群值,您可以删除、变换或插补它们:选择将再次取决于数据语境。因此,再次强调,理解数据并识别离群值的成因非常重要:
您可以使用上一节介绍的函数来处理数据中的离群值。
注意 该步骤通常与其他数据科学任务迭代进行:您会构建模型并验证,然后可能决定调整特征,再次迭代构建模型,依此往复。
您可以通过从原始数据创建有助于学习过程的特征,来提升学习算法的预测能力。这一过程通过从现有原始特征中创造出额外的相关特征来实现。
熟练掌握特征工程需要时间;如何处理原始数据以提升预测能力并不总是显而易见。但也许下面的清单能在您为数据集寻找特征工程方法时提供一些帮助:
factorize()
cut()
提示:更深入地了解 Scikit-Learn 的预处理模块,您会发现其中包含一些实用函数,能帮助您为数据构思新特征!
需要注意的是,这些只是工程化新特征、让数据更具预测性的部分方法!关键在于不断脑暴新特征或将旧特征组合起来,并使用 Scikit-Learn 测试其效果。
进行特征选择时,您会从原始数据特征中选出关键子集,以降低训练问题的维度。这看起来与您可能已经了解的其他降维技术(如 PCA)非常相似。但二者有区别:PCA 会将相似(相关)的属性合并并创建新的属性,被认为优于数据集中的原始属性。特征选择并不合并属性:它评估属性的质量与预测能力,并选出最佳集合。
要寻找重要特征,您可以使用随机森林算法:它会随机生成数千棵决策树,并轮流在拟合模型时剔除每个变量。通过这种方式,您可以计算当剔除某个变量时,模型表现是变好还是变差。您可以使用 Scikit-Learn Python 库来实现该算法:
您会看到,最佳特征集合包含花瓣长度和花瓣宽度数据。
注意 您还可以使用 Matplotlib 可视化特征选择的结果:
# Import `pyplot` and `numpy`import matplotlib.pyplot as pltimport numpy as np# Isolate feature importances importance = rfc.feature_importances_# Sort the feature importances sorted_importances = np.argsort(importance)# Insert paddingpadding = np.arange(len(names)-1) + 0.5# Plot the dataplt.barh(padding, importance[sorted_importances], align='center')# Customize the plotplt.yticks(padding, names[sorted_importances])plt.xlabel("Relative Importance")plt.title("Variable Importance")# Show the plotplt.show()
在数据探索的后续步骤中,您可以识别数据中的模式,包括数据属性之间或缺失数据之间的相关性。可视化是实现这一目标的有力工具;而且并不一定是静态的:可以尝试使用 Python 的 Bokeh 或 Plotly 库创建交互式可视化。
在以数字方式对数据进行定量分析之后,从视觉角度审视数据也很有用。是时候以可视化的方式来探索数据了。
为快速便捷地做到这一点,您可以使用 Python 的数据可视化库 Matplotlib。阻碍您的,恰恰是数据本身:您非常清楚,数据包含 64 列或特征。当您拥有如此之多的特征时,就称为“高维数据”。
关于何为“维度数据”,您会在我们的机器学习教程中学习,但目前只需理解:如果要在 2D 或 3D 图中可视化数据,您的数据仅应包含两个或三个维度。这意味着您需要对数据进行降维。
这就需要使用降维技术,例如主成分分析(PCA):
当您检查降维后的数据时,会发现列或特征已减少为仅两个。行数或观测数仍保持不变,即 3823。现在数据的格式已合适,可以开始绘图了!
选择合适的图表是一个很好的开始,但您会选择哪一种?
在本例中,您正在探索数据,可能希望发现数据属性之间的潜在相关性。散点图可能是可视化这一点的好方法:它允许您识别由降维得到的两个特征之间的关系。
import matplotlib.pyplot as pltplt.scatter(reduced_data[:,0], reduced_data[:,1], c=labels, cmap = 'viridis')plt.show()
其次,您也可以考虑使用 Bokeh 构建交互式图表,以发现数据属性之间的相关性。Bokeh 是一个用于现代 Web 浏览器呈现的 Python 交互式可视化库。如果您处理大型或流式数据集,它非常理想;但正如下例所示,它也适用于“常规”数据。
代码非常简单:导入必要模块,构建散点图,配置默认输出状态,使得在调用 show() 时将输出保存到文件。最后调用 show() 查看您构建的散点图!
show()
# Import the necessary modulesfrom bokeh.charts import Scatter, output_file, show# Construct the scatter plotp = Scatter(iris, x='Petal_length', y='Petal_width', color="Class", title="Petal Length vs Petal Width", xlabel="Sepal Length", ylabel="Sepal Width")# Output the file output_file('scatter.html')# Show the scatter plotshow(p)
结果非常雅致:
请注意,这是一张静态的已保存图片,但在您的笔记本或终端中生成的图表将是交互式的!当然,这只是使用 Bokeh 制作交互式图形的一个简单示例。务必查看 Bokeh Gallery 获取更多灵感,或学习 DataCamp 的使用 Bokeh 进行交互式数据可视化课程。
前面各节中的图形是探索数据属性间相关性的可视化方式。但这并不意味着您不能以定量方式探索这一度量!当您决定这么做时,请使用 Pandas 的 corr() 函数。但请注意,计算中将排除 NaN 或空值!
corr()
注意 后两种相关性度量在计算系数之前需要先对数据进行排序。您可以使用 rank() 轻松完成:在上述练习中,iris 数据已通过执行 iris.rank() 为您排好序。
rank()
iris
iris.rank()
此外,这些相关性计算也有一些前提假设:皮尔逊(Pearson)相关假定您的变量服从正态分布,变量之间满足线性关系,且数据沿回归线呈正态分布。而斯皮尔曼(Spearman)相关则假定您有两个有序变量,或两者之间存在某种关系,但不一定是线性的。
Kendall Tau 相关是一种系数,表示两列排好序的数据之间的一致性程度。您可以使用斯皮尔曼相关来衡量两个变量之间的相关程度。它们看起来非常相似,不是吗?
尽管 Kendall 和 Spearman 的相关度量看似相似,但它们确有不同:差异在于计算方式不同。Kendall Tau 系数由“一致对数减去不一致对数,再除以配对总数”得到。Spearman 系数则是“偏差平方和除以 n 乘以 n 减 1”。
n
Spearman 系数通常会大于 Kendall Tau 系数,但并非总是如此:当数据观测之间偏差很大时,您会得到更小的 Spearman 系数。Spearman 相关对此非常敏感,在某些情况下这可能很有用!
那么,何时应使用哪一种系数?因为这两种相关性实际上检验的内容不同;Kendall Tau 表示相对于不一致对的“一致对比例”,而 Spearman 系数并不这么做。您也可以认为 Kendall Tau 相关具有更直观的解释、更易于计算、对总体参数的估计更好,且在小样本下 p 值更准确。
提示 添加 print() 函数即可查看具体列之间成对相关性的计算结果。
print()
恭喜,您已经完成了我们的 Pandas 教程!现在,您已经掌握了一些可以用 Python 探索数据的基本技术。
如果您想更深入地钻研该主题,我们的 Pandas 课程系列正合适:查看我们的使用 pandas 进行数据操作、使用 pandas 重塑数据或使用 pandas 连接数据课程。
然而,如果您准备从 Pandas 转向,进一步探索 Matplotlib 包,不妨学习 DataCamp 的Python 数据可视化教程,或开始对数据建模!继续阅读我们的机器学习教程,了解如何构建一个能自动识别手写数字的机器学习模型!
Python 课程
课程