做数据分析时,对数据越了解,越有助于我们去分析,本文介绍如何使用Pandas探索数据。
1. Pandas简介
Pandas是Python中一个高性能库,提供了非常易用的数据结构以及丰富的函数工具用来做数据分析,所以该库在数据分析领域用的非常广泛。使用Pandas的关键点在于理解Pandas的两个核心数据结构:Series和DataFrame。
1.1 Series
Series表示带有标签的一维数组(one-dimensional labeled array):
- 数组内的元素可以是任意类型;
- label称为index,index可以不唯一,但必须是可哈希的类型(hashable type)。
构造Series结构最常用的方式就是使用pandas.Series
类,参数及说明如下:
pandas.Series(data=None, index=None, dtype=None, name=None, copy=False, fastpath=False)
- data:数组中的数据,参数可以是数组、字典或标量值
- index:标签或索引,可以重复,但必须是可哈希类型。参数可以是数组或一维的Index类型,长度必须和数据的长度相同;如果数据是字典类型,又显式的传了index,会覆盖字典的key;默认的index是(0, 1, 2, ..., len(data)-1)
- dtype:numpy.dtype或者None,如果传None的话,会自动检测类型。
- copy:布尔值,是否拷贝输入的值,默认是False。
下面列举几个创建Series的例子。
In [1]: import pandas as pd
In [2]: import numpy as np
# 使用数组创建Series,并指定index
In [3]: arr = np.array([1,2,3,4,5])
In [4]: s = pd.Series(arr, index=['a','b','c','d','a'])
In [5]: s
Out[5]:
a 1
b 2
c 3
d 4
a 5
dtype: int64
In [6]: s.index
Out[6]: Index(['a', 'b', 'c', 'd', 'a'], dtype='object')
# 使用数组创建Series,且使用默认的index
In [7]: pd.Series(np.random.randn(5))
Out[7]:
0 -1.316523
1 -1.211854
2 -0.532214
3 -0.143331
4 0.335070
dtype: float64
# 通过字典创建Series
In [8]: d = {'b':1, 'a':0, 'c':2}
In [9]: pd.Series(d)
Out[9]:
a 0
b 1
c 2
dtype: int64
# 使用标量创建Series,要注意此时标量重复len(index)次
In [10]: pd.Series(5., index=['a','b','c','d','e'])
Out[10]:
a 5.0
b 5.0
c 5.0
d 5.0
e 5.0
dtype: float64
在时间序列预测中Series数据结构将非常有用。
1.2 DataFrame
DataFrame和Series类似,但DataFrame是二维的,非常类似于关系型数据库里面的表。我们一般把列标签依旧称为index,而把行标签称为Column,对应的也有着两个参数去指定行列标签。DataFrame对象的构造方法和Series极其类似,参数情况如下:
pandas.DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)
这里不再赘述了,看以下一些例子:
In [15]: d = { 'one': pd.Series([1., 2., 3.], index=['a', 'b', 'c']),
...: 'two': pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])}
...:
In [16]: d
Out[16]:
{'one': a 1.0
b 2.0
c 3.0
dtype: float64, 'two': a 1.0
b 2.0
c 3.0
d 4.0
dtype: float64}
In [17]: df = pd.DataFrame(d)
In [18]: df
Out[18]:
one two
a 1.0 1.0
b 2.0 2.0
c 3.0 3.0
d NaN 4.0
In [19]: pd.DataFrame(d, index=['d', 'b', 'a'])
Out[19]:
one two
d NaN 4.0
b 2.0 2.0
a 1.0 1.0
In [20]: pd.DataFrame(d, index=['d', 'b', 'a'], columns=['two', 'three'])
Out[20]:
two three
d 4.0 NaN
b 2.0 NaN
a 1.0 NaN
In [21]: df.index
Out[21]: Index(['a', 'b', 'c', 'd'], dtype='object')
In [22]: df.columns
Out[22]: Index(['one', 'two'], dtype='object')
注:在Pandas中,缺失值一般用NaN表示。
会创建Series和Pandas对象只是学习Pandas的第一步,其实Pandas更加强大的地方在于它在这两个核心数据结构之上提供了非常丰富的函数和方法,让我们可以更专注于数据分析本身。本文的重点不是介绍Pandas,所以Pandas的介绍到此为止,有兴趣的可以看起官方文档:http://pandas.pydata.org/pandas-docs/stable/index.html。里面有一个10分钟的入门教程,对于只想快速了解一下的同学是个非常不错的选择。
下面我们言归正传,看一下如何利用Pandas提供的各种工具来探索我们的数据。
2. 探索数据
数据说明:本次示例所用的数据来自于https://archive.ics.uci.edu/ml/datasets/bank+marketing,是葡萄牙银行做的一次电话调查,旨在判断用户对于行方定期存储产品的认购情况。数据包含了很多列,有些列的值是标量型的,有些是数值型的。本文的重点在于如何利用Pandas工具去探索数据(分布)情况,所以列的含义不是那么重要,这里就不解释了,有兴趣的可以去上面给出的链接处查看,有详细的说明。
导入相关的包并读入数据:
In [1]: import numpy as np
In [2]: import pandas as pd
In [3]: import matplotlib.pyplot as plt
In [4]: df = pd.read_csv('SampleData/banking.csv')
2.1 统计信息
1,查看数据基本信息。
# head默认显示5条数据,可以指定显示几条
In [5]: df.head()
Out[5]:
age job marital education default housing loan \
0 44 blue-collar married basic.4y unknown yes no
1 53 technician married unknown no no no
2 28 management single university.degree no yes no
3 39 services married high.school no no no
4 55 retired married basic.4y no yes no
contact month day_of_week ... campaign pdays previous poutcome \
0 cellular aug thu ... 1 999 0 nonexistent
1 cellular nov fri ... 1 999 0 nonexistent
2 cellular jun thu ... 3 6 2 success
3 cellular apr fri ... 2 999 0 nonexistent
4 cellular aug fri ... 1 3 1 success
emp_var_rate cons_price_idx cons_conf_idx euribor3m nr_employed y
0 1.4 93.444 -36.1 4.963 5228.1 0
1 -0.1 93.200 -42.0 4.021 5195.8 0
2 -1.7 94.055 -39.8 0.729 4991.6 1
3 -1.8 93.075 -47.1 1.405 5099.1 0
4 -2.9 92.201 -31.4 0.869 5076.2 1
[5 rows x 21 columns]
# 查看数据维度
In [6]: df.shape
Out[6]: (41188, 21)
# 查看数据类型
In [7]: df.dtypes
Out[7]:
age int64
job object
marital object
education object
default object
housing object
loan object
contact object
month object
day_of_week object
duration int64
campaign int64
pdays int64
previous int64
poutcome object
emp_var_rate float64
cons_price_idx float64
cons_conf_idx float64
euribor3m float64
nr_employed float64
y int64
dtype: object
通过查看基本信息,我们可以查看到一些示例数据,以及数据总条数、维度数,各个维度的类型等,这些都是我们探索数据的第一步。
2,通过Pandas的describe
方法查看一些汇总信息,探索各个维度值的分布情况:
In [11]: df.describe()
Out[11]:
age duration campaign pdays previous \
count 41188.00000 41188.000000 41188.000000 41188.000000 41188.000000
mean 40.02406 258.285010 2.567593 962.475454 0.172963
std 10.42125 259.279249 2.770014 186.910907 0.494901
min 17.00000 0.000000 1.000000 0.000000 0.000000
25% 32.00000 102.000000 1.000000 999.000000 0.000000
50% 38.00000 180.000000 2.000000 999.000000 0.000000
75% 47.00000 319.000000 3.000000 999.000000 0.000000
max 98.00000 4918.000000 56.000000 999.000000 7.000000
emp_var_rate cons_price_idx cons_conf_idx euribor3m \
count 41188.000000 41188.000000 41188.000000 41188.000000
mean 0.081886 93.575664 -40.502600 3.621291
std 1.570960 0.578840 4.628198 1.734447
min -3.400000 92.201000 -50.800000 0.634000
25% -1.800000 93.075000 -42.700000 1.344000
50% 1.100000 93.749000 -41.800000 4.857000
75% 1.400000 93.994000 -36.400000 4.961000
max 1.400000 94.767000 -26.900000 5.045000
nr_employed y
count 41188.000000 41188.000000
mean 5167.035911 0.112654
std 72.251528 0.316173
min 4963.600000 0.000000
25% 5099.100000 0.000000
50% 5191.000000 0.000000
75% 5228.100000 0.000000
max 5228.100000 1.000000
可以看到该方法默认只计算了数值型维度的5个方面的信息:
- count:总数
- mean:均值
- std:标准差
- min:最小值
- 25%:第一四分位数或较小四分位数(Q1):等于该样本中所有数值由小到大排列后第25%的数字。
- 50%:第二四分位数或中位数(Q2):等于该样本中所有数值由小到大排列后第50%的数字。
- 75%:第三四分位数或较大四分位数(Q3):等于该样本中所有数值由小到大排列后第75%的数字。
- max:最大值。
当然,对于数值型数据describe
方法会统计上面5个方面的信息,对于标称型数据则统计另外4个方面的信息:
In [13]: df.describe(exclude=[np.number])
Out[13]:
job marital education default housing loan contact \
count 41188 41188 41188 41188 41188 41188 41188
unique 12 4 8 3 3 3 2
top admin. married university.degree no yes no cellular
freq 10422 24928 12168 32588 21576 33950 26144
month day_of_week poutcome
count 41188 41188 41188
unique 10 5 3
top may thu nonexistent
freq 13769 8623 35563
这4方面的信息包括:
- count:总数
- unique:去重后的个数
- top:出现频率最高的值
- freq:出现最高频率的值的频率
对于Timestamp类型还会有first和last两个信息。
3,通过groupby
查看各个标称型维度值的分布情况。describe方法对于探索数值型数据的分布非常有用,但对于标称型数据虽然也有统计,但还不够。往往我们更多的使用groupby
方法,该方法与SQL中的groupby类似,这里举几个例子:
In [14]: df.groupby('education').size()
Out[14]:
education
basic.4y 4176
basic.6y 2292
basic.9y 6045
high.school 9515
illiterate 18
professional.course 5243
university.degree 12168
unknown 1731
dtype: int64
In [15]: df.groupby('y').size()
Out[15]:
y
0 36548
1 4640
dtype: int64
4,有很多算法要求所选取的维度之间要没有相关性,所以探索维度之间的相关性也非常重要。Pandas提供了corr
方法可以计算相关系数(默认计算皮尔逊相关系数):
In [16]: df.corr()
Out[16]:
age duration campaign pdays previous \
age 1.000000 -0.000866 0.004594 -0.034369 0.024365
duration -0.000866 1.000000 -0.071699 -0.047577 0.020640
campaign 0.004594 -0.071699 1.000000 0.052584 -0.079141
pdays -0.034369 -0.047577 0.052584 1.000000 -0.587514
previous 0.024365 0.020640 -0.079141 -0.587514 1.000000
emp_var_rate -0.000371 -0.027968 0.150754 0.271004 -0.420489
cons_price_idx 0.000857 0.005312 0.127836 0.078889 -0.203130
cons_conf_idx 0.129372 -0.008173 -0.013733 -0.091342 -0.050936
euribor3m 0.010767 -0.032897 0.135133 0.296899 -0.454494
nr_employed -0.017725 -0.044703 0.144095 0.372605 -0.501333
y 0.030399 0.405274 -0.066357 -0.324914 0.230181
emp_var_rate cons_price_idx cons_conf_idx euribor3m \
age -0.000371 0.000857 0.129372 0.010767
duration -0.027968 0.005312 -0.008173 -0.032897
campaign 0.150754 0.127836 -0.013733 0.135133
pdays 0.271004 0.078889 -0.091342 0.296899
previous -0.420489 -0.203130 -0.050936 -0.454494
emp_var_rate 1.000000 0.775334 0.196041 0.972245
cons_price_idx 0.775334 1.000000 0.058986 0.688230
cons_conf_idx 0.196041 0.058986 1.000000 0.277686
euribor3m 0.972245 0.688230 0.277686 1.000000
nr_employed 0.906970 0.522034 0.100513 0.945154
y -0.298334 -0.136211 0.054878 -0.307771
nr_employed y
age -0.017725 0.030399
duration -0.044703 0.405274
campaign 0.144095 -0.066357
pdays 0.372605 -0.324914
previous -0.501333 0.230181
emp_var_rate 0.906970 -0.298334
cons_price_idx 0.522034 -0.136211
cons_conf_idx 0.100513 0.054878
euribor3m 0.945154 -0.307771
nr_employed 1.000000 -0.354678
y -0.354678 1.000000
皮尔逊相关系数取值范围为[-1, 1],-1表示(线性)负相关,0表示(线性)无关,1表示(线性)正相关。通过这个(对角)矩阵,我们可以很容易的看出各个属性间的相关性。
5,pandas还提供了skew
来计算偏度(skew):衡量实数随机变量概率分布的不对称性。偏度的值可以为正,可以为负或者甚至是无法定义。在数量上,偏度为负(左偏态或负偏态,Negative Skew)就意味着在概率密度函数左侧的尾部比右侧的长,绝大多数的值(包括中位数在内)位于平均值的右侧。偏度为正(右偏态或正偏态,Positive Skew)就意味着在概率密度函数右侧的尾部比左侧的长,绝大多数的值(但不一定包括中位数)位于平均值的左侧。如图:
偏度为零就表示数值相对均匀地分布在平均值的两侧,但不一定意味着其为对称分布。如果分布对称,那么平均值=中位数,偏度为零(此外,如果分布为单峰分布,那么平均值=中位数=众数)。
In [17]: df.skew()
Out[17]:
age 0.784697
duration 3.263141
campaign 4.762507
pdays -4.922190
previous 3.832042
emp_var_rate -0.724096
cons_price_idx -0.230888
cons_conf_idx 0.303180
euribor3m -0.709188
nr_employed -1.044262
y 2.450330
dtype: float64
2.2 可视化
统计信息虽然非常精确,但看上去并不是非常直观,我们可以通过一些可视化的手段来非常直观的探索数据分布。
1,直方图(histogram):
In [20]: %matplotlib
Using matplotlib backend: MacOSX
In [21]: df.hist(figsize=(12, 8))
2,密度图(density plot):
In [22]: df.plot(kind='density', subplots=True, figsize=(12,8), layout=(3,4), sharex=False)
3,箱型图(boxplots):
In [23]: df.plot(kind='box', subplots=True, figsize=(12,8), layout=(3,4), sharex=False, sharey=False)
箱型图的含义参见:箱型图介绍。
4,相关系数矩阵图:
corr = df.corr()
figure = plt.figure(figsize=(12,8))
ax = figure.add_subplot(111)
cax = ax.matshow(corr, vmin=-1, vmax=1)
figure.colorbar(cax)
plt.show() # 0~10,依次对应age~y
5,通过散点矩阵图(scatter matrix)查看各维度相关性:
from pandas.plotting import scatter_matrix
scatter_matrix(df, figsize=(18, 12))
关于scatter matrix需要解释一下,和上面的相关系数矩阵图类似,该图也描述了各维度间的相关性。而对角线上是各个维度自己与自己的相关性,显然都是完全相关的,也就是一条直线(皮尔逊相关系数为1),这没什么用。所以Pandas就把对角线上面的改为展示维度的密度图了。这里再附上皮尔逊相关系数的值与其图形的关系(图片来自皮尔逊相关系数维基百科):
以及一个比较泛(不是非常的严格和通用)的判断相关性强弱的标准:
相关性 | 负 | 正 |
---|---|---|
无 | -0.09~0.0 | 0.0~0.09 |
弱 | -0.3~-0.1 | 0.1~0.3 |
中 | -0.5~-0.3 | 0.3~0.5 |
强 | -1.0~-0.5 | 0.5~1.0 |
可视化可以帮助我们“定性的”了解数据,统计信息则帮助我们“定量的”了解数据,二者结合可以使我们更加了解自己的数据,从而选择下一步的数据处理流程。除了本文已经介绍的之外,Pandas还有非常非常多的工具帮助我们分析数据,可以查看其文档慢慢积累。
本文源码见这里。
References:
- 维基百科(具体各个链接见博客内容)。
- Pandas官方文档.
- Machine Learning Mastery with Python.
十分感谢!!
后面的运行也出现了错误。可以指点迷津吗?或者可以分享一下你下载的数据吗?
https://github.com/niyanchun/AI_Learning/blob/master/SampleData/banking.csv
df.plot(kind='density', subplots=True, figsize=(12,8), layout=(3,4), sharex=False)
df.plot(kind='box', subplots=True, figsize=(12,8), layout=(3,4), sharex=False, sharey=False)
前面可以一直执行。jupyter是不是会运行比较慢呢?这两个一直没有出图
大神,你好,我是一个python新手,最近有一份数据挖掘的作业,便浏览到了大佬您的代码,但是我在用df.describe()的时候数字并没有对齐,这对后面的运行会不会有影响呢?
没影响
请问可否分享一下python源代码以及数据呢?
https://github.com/niyanchun/AI_Learning/blob/master/DataExplorer/explore_data_using_pandas.ipynb