本文概述
编者按:让·尼古拉斯·霍尔德(Jean-Nicholas Hould)是蒙特利尔英特尔安全公司的数据科学家, 他在其博客上教如何入门数据科学。
探索性数据分析(EDA)是一种统计方法, 旨在发现和汇总数据集。在数据科学过程的这一步, 你想探索数据集的结构, 变量及其关系。
在本文中, 你将重点研究探索性数据分析的一个方面:数据概要分析。
数据分析就是通过描述性统计数据汇总数据集。你想使用过多的度量值来更好地理解你的数据集。在分析数据集时, 数据类型, 缺失值, 均值, 中位数和标准偏差只是你需要收集的许多元素中的一部分。数据概要分析的目的是对数据有扎实的了解, 以便以后可以开始以各种方式查询和可视化数据。
知道数据来自何处
在跳入任何EDA之前, 你应该尽可能多地了解要分析的数据的来源。你需要了解如何收集数据以及如何处理数据。数据上是否有任何过去的转换会影响你的分析?
你应该能够在数据集上回答这些问题:
- 它是如何收集的?
- 是样品吗?
- 采样是否正确?
- 数据集是否以任何方式转换?
- 数据集中是否存在一些已知问题?
如果你不了解数据的来源, 那么将很难从数据集中得出有意义的结论。你也有犯非常重要的分析错误的风险。
此外, 你应确保数据集以标准化的方式构造。推荐的格式是第三种标准格式, 也称为整洁数据。 “整洁”的数据集具有以下属性:
- 每个变量组成一列并包含值
- 每个观察结果排成一行
- 每种观察单位组成一个表格
尊重这种标准化格式可以加快你的分析速度, 因为它与许多工具和库兼容。
数据剖析
在本文中, 你将使用CraftCans网站上的Craft Beers数据集。该数据集仅包含来自美国啤酒厂的罐装啤酒的数据。网站上尚不清楚该数据集是否报告了在美国酿造的每种罐装啤酒。为了安全起见, 你将认为此数据集是一个可能包含偏差的样本。
这是你将使用的数据集的结构:
啤酒:
- ID:啤酒的唯一标识符。
- 名称:啤酒的名称。
- ABV:按啤酒量计算的酒精含量。
- IBU:啤酒的国际苦味股。
- 风格:啤酒的风格。
- 盎司:啤酒。
啤酒厂:
- ID:啤酒厂的唯一标识符。
- 名称:啤酒厂的名称。
- 城市:啤酒厂所在的城市。
- 州:啤酒厂所在的州。
数据类型
第一步是了解数据集的组成。
你要处理什么变量?
通常, 你可以将数据拟合为以下类别之一:
- 数值型
- 分类的
- 文本
- 日期
首先, 你将使用pandas的from_csv函数导入可在此存储库中找到的数据集。你还将啤酒和啤酒厂的数据集结合在一起, 以方便进行后续分析。
import pandas as pd
beers = pd.DataFrame.from_csv("https://raw.githubusercontent.com/nickhould/craft-beers-dataset/master/data/craftcans_beers.csv")
breweries = pd.DataFrame.from_csv("https://raw.githubusercontent.com/nickhould/craft-beers-dataset/master/data/craftcans_breweries.csv")
beers_and_breweries = pd.merge(beers, breweries, how='inner', left_on="brewery_id", right_on="id", sort=True, suffixes=('_beer', '_brewery'))
使用pandas库, 你可以运行dtypes函数列出每一列及其数据类型。
beers.dtypes
得到以下结果:
abv float64
ibu float64
id int64
name object
style object
brewery_id int64
ounces float64
dtype: object
如上所见, 该功能无法对不同的数据类型进行干净的分组。我们不希望将各种数值数据类型(float64和int64)分组为一个类别。另外, 有些列被列为对象, 这不是很有帮助。
要解决此问题, 你可以构建自己的函数, 该函数将确定DataFrame中每一列的类别。
def get_var_category(series):
unique_count = series.nunique(dropna=False)
total_count = len(series)
if pd.api.types.is_numeric_dtype(series):
return 'Numerical'
elif pd.api.types.is_datetime64_dtype(series):
return 'Date'
elif unique_count==total_count:
return 'Text (Unique)'
else:
return 'Categorical'
def print_categories(df):
for column_name in df.columns:
print(column_name, ": ", get_var_category(df[column_name]))
啤酒变量
print_categories(beers)
上面的命令为你提供以下结果:
abv : Numerical
ibu : Numerical
id : Numerical
name : Categorical
style : Categorical
brewery_id : Numerical
ounces : Numerical
啤酒厂变量
print_categories(breweries)
得到以下结果:
name : Categorical
city : Categorical
state : Categorical
id : Numerical
有了这些信息, 你就可以更好地了解我们的数据集。你知道你只在处理分类和数字数据。数值变量可用于提取许多不同的度量值, 例如平均值, 标准偏差等。分类变量通常是对数据进行分段和分组的有趣方式。例如, 你可能想了解IBU在各种啤酒类型之间的差异。
描述性统计
在本部分中, 你将遍历各种描述性统计数据, 这些统计数据可用于更好地理解我们的数据。你会注意到, 单独进行这些测量并不是很有帮助。这些不同的度量值的组合是你可以获取最大价值的地方。
你将重点关注IBU变量, 因为它是一个数字变量。与分类变量相比, 这种类型的变量提供了更广泛的测量范围。你仍然可以对分类变量进行测量, 但会受到更多限制。
长度
len函数计算系列中观测值的数量。该函数将计算所有观察值, 无论值是否缺失或为空。
length = len(beers["ibu"])
print(length)
在本系列中, 我们总共有2410个观测值。
计数
计数功能将返回系列中非NA /非空观测值的数量。
count = beers["ibu"].count()
print(count)
如你所见, 系列中有1405个非空观测值。
缺失值
使用”长度”和”计数”, 我们现在能够计算缺失值的数量。缺失值的数量是”长度”和”计数”之间的差。
number_of_missing_values = length - count
pct_of_missing_values = float(number_of_missing_values / length)
pct_of_missing_values = "{0:.1f}%".format(pct_of_missing_values*100)
print(pct_of_missing_values)
要以百分比形式输出缺失值, 只需将缺失值的数量除以观测值的总数即长度即可。浮点函数用于确保在除法中捕获小数。格式化功能用于将数字很好地格式化为百分比。
在这种情况下, 你将丢失几乎42%的IBU变量。这对你来说很重要, 因为它会影响你的分析。大多数描述性统计信息将忽略那些缺失的值, 这肯定会引起偏差。
最小值/最大值
使用系列上的min和max函数可以轻松获得数据集的最小值和最大值。
print("Minimum value: ", beers["ibu"].min())
print("Maximum value: ", beers["ibu"].max())
最小值/最大值有助于了解变量中的值范围。在这种情况下, IBU的范围是4到138。
模式
模式是数据集中最频繁的值。可以使用系列的模式功能获得。
print(beers["ibu"].mode())
在正态分布中, 众数等于均值和中位数。
在这种情况下, IBU变量的模式为20。这是数据集中最常见的IBU。
意思
均值是集中趋势的度量。它代表值的总和除以非缺失观测值的数量。
可以通过Series上的均值函数获得。
mean = beers["ibu"].mean()
均值容易受到异常值的影响。一些极值可以极大地改变平均值, 将其向上或向下拖动。
中位数
中位数也是衡量集中趋势的指标。它是恰好在数值的有序列表中间的数字。
median = beers["ibu"].median()
在偏态分布的情况下, 中位数比集中度更好地衡量了集中趋势。
对于IBU分布, 均值和中位数处于相同数量级。
标准偏差
标准偏差是色散的量度。高标准偏差表示数据点分布在很大的值范围内。标准偏差以与值相同的单位表示。
standarddev = beers["ibu"].std()
在这种情况下, 标准偏差为〜26。 25.954065911259324是准确的如果IBU的分布是正态分布, 你会知道〜68%的观测值在平均值的一个标准偏差内。
分位数统计
分位数是切分点, 它们将分布拆分成相等的大小。许多分位数都有自己的名称。如果将分布分为四个相等的组, 则创建的分位数称为四分位数。你可以使用系列上的分位数功能轻松创建分位数。你可以将具有不同分位数的数组传递给该函数以进行计算。在以下情况下, 我们要将分布分为四个相等的组。
quantile = beers["ibu"].quantile([.25, .5, .75])
0.25 | 21.0 |
0.50 | 35.0 |
0.75 | 64.0 |
姓名:妈妈, | dtype:float64 |
如上所示, 50%的分位数等于中位数。它是将数据集分成两半的值。你还可以注意到, 有75%的观测值等于或低于64 IBU。此外, 分布的50%位于21和64 IBU之间。请务必注意, 这些指标未考虑缺失值。
分布图
可视化在探索性数据分析中非常有用。在本文中, 我们将不讨论主题可视化。但是, 我们不能不谈数据配置, 而不必提及频率分布图的重要性。它是最简单但功能最强大的可视化之一。它展示了我们数据集中每个值的频率。
为了创建这种可视化效果, 我们使用了带展示功能的seaborn库。该函数期望aSeries`不会缺少任何值。
import seaborn as sns
sns.set(color_codes=True)
sns.set_palette(sns.color_palette("muted"))
sns.distplot(beers["ibu"].dropna());
在此分布图中, 你可以清楚地看到一些我们先前计算的值。最小值接近0 IBU, 最大值接近140 IBU。你清楚地看到最频繁的值接近20 IBU。除此信息外, 我们现在看到接近60 IBU的峰值。
为什么在此分布中有两个峰值?
有什么可以解释的?这是我们在探索性数据分析的第二阶段中可以探索的一个方面。
相关性
关联是发现数值变量之间关系的好方法。有多种计算相关性的方法。皮尔逊相关系数是一种广泛使用的方法, 用于测量两个变量之间的线性相关性。相关系数的范围是-1至1。相关系数1是总正相关, 相关系数-1是总负相关, 而相关系数0是非线性相关。我们可以使用Series上的corr函数执行该计算。默认情况下, 此函数将使用Pearson相关系数计算。通过此功能可以使用不同的计算方法。
beers[["abv", "ibu", "ounces"]].corr()
抗体 | 妈妈 | 盎司 | |
抗体 | 1 | 0.670621 | 0.172529 |
妈妈 | 0.670621 | 1 | 0.054691 |
盎司 | 0.172529 | 0.054691 | 1 |
如上所示, IBU与自身之间的相关性为1。显然, 数值变量与自身之间具有完美的相关性。更有趣的是, 你可以看到ABV和IBU的相关性等于0.670621。虽然这不是总的正相关, 但仍然是高度相关。这是一个有趣的方面, 我们可以进一步探索。
关于非数值变量的一些注意事项
先前提取的度量标准仅适用于数值。如果你正在处理其他类型的数据(例如分类数据), 则仍可以收集一些有趣的度量。你可以计算数据集中每个值的频率。
DataFrame有一个名为describe的函数, 用于汇总数据集。如果你的DataFrame仅具有分类或文本值, 则摘要将专门针对此类数据进行调整。
beers[["name", "style"]].describe()
名称 | 样式 | |
计数 | 2410 | 2405 |
独特 | 2305 | 99 |
最佳 | 直达跳车 | 美国IPA |
频率 | 12 | 424 |
分析库
如上所述, 收集描述性统计信息可能是一个乏味的过程。很高兴地发现, 有一些可以为你执行所有数据处理的库。他们输出的数据非常清晰。熊猫分析是其中之一。该库提供了数据集的现成统计分析。由于我们使用的数据集是整齐和标准化的, 因此我们可以立即在我们的数据集上使用该库。
import pandas_profiling
pandas_profiling.ProfileReport(beers_and_breweries)
更多问题
通常, 一旦对数据集进行了概要分析, 就会比最初提出更多的问题。很好, 因为这些新问题将助你进行探索性数据分析。
在进行此概要分析时, 我们收集了以下几个问题:
- 41.7%的IBU值丢失。这是为什么?这如何影响我们的分析?
- IBU分布有两个高峰。是什么解释了这一点?
- 是什么解释了IBU和ABV之间的关系?啤酒风格在这种关联中有什么影响?
- 地理区域之间的IBU, ABV或样式是否有差异?东海岸vs西海岸呢?
数据分析不是线性过程。在对数据集进行过滤和细分时, 你将回到数据集并收集有关数据子组的描述性统计信息。
下一步
在本文中, 你已经了解了如何分析数据集。现在, 你知道如何将变量归因于特定的数据类型组。你还计算了数据集上的不同描述统计量, 并且了解了如何解释这些度量。最后, 你已经看到有一些库可以帮助你进行处理以分析数据集。更重要的是, 你产生了比以往更多的问题来推动你的探索性数据分析。
评论前必须登录!
注册