查看原文
其他

用Python玩转统计数据:取样、计算相关性、拆分训练模型和测试

Tomasz Drabas 大数据 2019-06-23


导读:本文会介绍一些技术,帮你更好地理解数据,以及探索特征之间的关系。


本文使用Python建立对数据的理解。我们会分析变量的分布,捋清特征之间的关系。最后,你会学习给样本分层,并将数据集拆分成测试集与训练集。


作者:托马兹·卓巴斯(Tomasz Drabas)

如需转载请联系大数据(ID:hzdashuju)



01 生成描述性的统计数据


要完全理解任何随机变量的分布,我们需要知道其平均数标准差最小值最大值中位数四分位数偏度峰度


1. 准备


要实践本技巧,你只需装好pandas模块。此外没有要求了。


2. 怎么做


下面的代码可以快速达成对数据的初步理解。假设数据已从CSV文件读出,并存于csv_read变量(data_describe.py文件)中:


csv_desc = csv_read[
[
'beds''baths''sq_tf''price''s_price',
'n_price''s_sq__ft''n_sq__ft''b_price',
'p_price''d_Condo''d_Multi-Family',
'd_Residential''d_Unkown'
]
].describe().transpose()
# 加上偏度,众数与峰度
csv_desc['skew'] = csv_read.skew(numeric_only=True)
csv_desc['mode'] = csv_read.mode(numeric_only=True).transpose()
csv_desc['kurtosis'] = csv_read.kurt(numeric_only=True)


3. 原理


pandas有个很管用的.describe()方法,它替我们做了大部分的工作。这个方法能生成我们想要的大部分描述变量;输出看起来是这样的(为清晰做了相应简化):


beds
count 981.000000
mean 2.914373
std 1.306502
min 0.000000
252.000000
503.000000
754.000000
max 8.000000


DataFrame对象的索引标明了描述性统计数据的名字,每一列代表我们数据集中一个特定的变量。不过,我们还缺偏度、峰度和众数。为了更方便地加入csv_desc变量,我们使用.transpose()移项了.describe()方法的输出结果,使得变量放在索引里,每一列代表描述性的变量。


你也可以手动计算平均数、标准差及其他描述性的统计数据。可用的方法列表见:

http://pandas.pydata.org/pandas-docs/stable/api.html#api-dataframe-stats


有了基础的统计数据,我们可以补上其他的。要留意的是,.skew(...)和.kurt(...)方法以类似的格式返回数据,而.mode(...)不然;.mode(...)方法返回的数据要进行调整,以便和.describe()方法的输出格式保持一致。


4. 更多


描述性的统计数据也可用SciPy和NumPy计算得到。当然,比起pandas来不那么直观(data_describe_alternative.py文件)。


首先加载两个模块。


import scipy.stats as st
import bumpy as np


然后从CSV文件读取数据:


r_filenameCSV = '../../Data/Chapter02/' + 'realEstate_trans_full.csv'
csv_read = np.genfromtxt(
r_filenameCSV,
delimiter=',',
names=True,
# 只有数字列
usecols=[4,5,6,8,11,12,13,14,15,16,17,18,19,20]
)


.genfromtxt(...)方法以文件名作为第一个(也是唯一必需的)参数。指定分隔符是一个好做法;本例中分隔符是',',也可以是\t。names参数指定为True,意味着变量名存于第一行。最后,usecols参数指定文件中哪些列要存进csv_read对象。

最终可以计算出要求的数据:


.genfromtxt(...)方法创建的数据是一系列元组。.describe(...)方法只接受列表形式的数据,所以得先(使用列表表达式)将每个元组转换成列表。


这个方法的输出可以说对用户不太友好:



5. 参考


查阅SciPy中的文档,了解所有统计函数:

http://docs.scipy.org/doc/scipy/reference/stats.html#statistical-functions



02 探索特征之间的相关性


两个变量之间的相关系数用来衡量它们之间的关系。系数为1,我们可以说这两个变量完全相关;系数为-1,我们可以说第二个变量与第一个变量完全负相关;系数0意味着两者之间不存在可度量的关系。


这里要强调一个基础事实:不能因为两个变量是相关的,就说两者之间存在因果关系。


要了解更多,可访问:

https://web.cn.edu/kwheeler/logic_causation.html


1. 准备


要实践本技巧,你要先装好pandas模块。此外没有要求了。


2. 怎么做


我们将测算公寓的卧室数目、浴室数目、楼板面积与价格之间的相关性。再一次,我们假设数据已经在csv_read对象中了。下面是代码(data_correlations.py文件):


# 计算相关性
coefficients = ['pearson''kendall''spearman']
csv_corr = {}
for coefficient in coefficients:
csv_corr[coefficient] = csv_read.corr(method=coefficient).transpose()


3. 原理


pandas可用于计算三种相关度:皮尔逊积矩相关系数、肯达尔等级相关系数和斯皮尔曼等级相关系数。后两者对于非正态分布的随机变量并不是很敏感。


我们计算这三种相关系数,并且将结果存在csv_corr变量中。DataFrame对象csv_read调用了.corr(...)方法,唯一要指定的参数是要使用的计算方法。结果如下所示:



4. 参考


你也可以使用NumPy计算皮尔逊相关系数:

http://docs.scipy.org/doc/numpy/reference/generated/numpy.corrcoef.html



03 数据取样


有时候数据集过大,不方便建立模型。出于实用的考虑(不要让模型的估计没有个尽头),最好从完整的数据集中取出一些分层样本


本文从MongoDB读取数据,用Python取样。


1. 准备


要实践本技巧,你需要PyMongo、pandas和NumPy。其他没有什么要准备的。


2. 怎么做


有两种做法:确定一个抽样的比例(比如说,20%),或者确定要取出的记录条数。下面的代码展示了如何提取一定比例的数据(data_sampling.py文件):


strata_frac = 0.2
client = pymongo.MongoClient()
db = client['packt']
real_estate = db['real_estate']
# 读取数据
sales = pd.DataFrame.from_dict(
list( real_estate.find(
{'beds': {'$in': [234]} },
{'_id'0'zip'1'city'1'price'1'beds'1'sq__ft'1}
)
)
)
# 取样
sample = pd.DataFrame()
for bed in [234]:
sample = sample.append(
sales[sales.beds == bed].sample(frac=strata_frac),
ignore_index=True
)


3. 原理


首先确定取样的比例,即strata_frac变量。从MongoDB取出数据。MongoDB返回的是一个字典。pandas的.from_dict(...)方法生成一个DataFrame对象,这样处理起来更方便。


要获取数据集中的一个子集,pandas的.sample(...)方法是一个很方便的途径。不过这里还是有一个陷阱:所有的观测值被选出的概率相同,可能我们得到的样本中,变量的分布并不能代表整个数据集。


在这个简单的例子中,为了避免前面的陷阱,我们遍历卧室数目的取值,用.sample(...)方法从这个子集中取出一个样本。我们可以指定frac参数,以返回数据集子集(卧室数目)的一部分。


我们还使用了DataFrame的.append(...)方法:有一个DataFrame对象(例子中的sample),将另一个DataFrame附加到这一个已有的记录后面。ignore_index参数设为True时,会忽略附加DataFrame的索引值,并沿用原有DataFrame的索引值。


4. 更多


有时,你会希望指定抽样的数目,而不是占原数据集的比例。之前说过,pandas的 .sample(...)方法也能很好地处理这种场景(data_sampling_alternative.py文件)。


首先,我们指定要从原数据集中抽样的记录数目:


strata_cnt = 200


要保持不同卧室数目的取值比例与原数据集一致,我们首先计算每个桶中该放的记录数:


ttl_cnt = sales['beds'].count()
strata_expected_counts = sales['beds'].value_counts() / ttl_cnt * strata_cnt


DataFrame的.count()方法会计算整个数据集中的总数目。然后,我们可以分别计算出各卧室数目下的比例,乘上strata_cnt变量,就得到了各自的记录条数。.value_counts()方法返回的是指定列(例子中的beds)中,每个值的数目。然后将数据集中每条记录除以ttl_cnt再乘以想要的样本大小。


抽样可以使用.sample(...)方法。不过,我们这次不指定frac参数了,而是指定要提取的记录数n:


for bed in beds:
sample = sample.append(
sales[sales.beds == bed] \
.sample(n=np.round(strata_expected_counts[bed])),
ignore_index=True
)



04 将数据集拆分成训练集、交叉验证集和测试集


要建立一个可信的统计模型,我们需要确信它精确地抽象出了我们要处理的现象。要获得这个保证,我们需要测试模型。要保证精确度,我们训练和测试不能用同样的数据集。


本技法中,你会学到如何将你的数据集快速分成两个子集:一个用来训练模型,另一个用来测试


1. 准备


要实践本技巧,你需要pandas、SQLAlchemy和NumPy。其他没有什么要准备的。


2. 怎么做


我们从PostgreSQL数据库读出数据,存到DataFrame里。通常我们划出20%~40%的数据用于测试。本例中,我们选出1/3的数据(data_split.py文件):


# 指定用于测试的数据比例
test_size = 0.33
# 输出样本的文件名
w_filenameTrain = '../../Data/Chapter02/realEstate_train.csv'
w_filenameTest = '../../Data/Chapter02/realEstate_test.csv'
# 用一个变量标记训练样本
data['train'] = np.random.rand(len(data)) < (1 - test_size)
# 区分训练集和测试集
train = data[data.train]
test = data[~data.train]


3. 原理


我们从指定划分数据的比例与存储数据的位置开始:两个存放训练集和测试集的文件。


我们希望随机选择测试数据。这里,我们使用NumPy的伪随机数生成器。.rand(...)方法生成指定长度(len(data))的随机数的列表。生成的随机数在0和1之间。


接着我们将这些数字与要归到训练集的比例(1-test_size)进行比较:如果数字小于比例,我们就将记录放在训练集(train属性的值为True)中;否则就放到测试集中(train属性的值为False)。


最后两行将数据集拆成训练集和测试集。~是逻辑运算“否”的运算符;这样,如果train属性为False,那么“否”一下就成了True。


4. 更多


SciKit-learn提供了另一种拆分数据集的方法。我们先将原始的数据集分成两块,一块是因变量y,一块是自变量x:


# 选择自变量和因变量
x = data[['zip''beds''sq__ft']]
y = data['price']


然后就可以拆了:


# 拆分
x_train, x_test, y_train, y_test = sk.train_test_split(
x, y, test_size=0.33, random_state=42)


.train_test_split(...)方法帮我们将数据集拆成互补的子集:一个是训练集,另一个是测试集。在每个种类中,我们有两个数据集:一个包含因变量,另一个包含自变量。


延伸阅读《数据分析实战

点击上图了解及购买

转载请联系微信:togo-maruko


推荐语:通过大量的现实案例,详细讲解数据分析相关的各种方法。



据统计,99%的大咖都完成了这个神操作



更多精彩


在公众号后台对话框输入以下关键词

查看更多优质内容!


PPT | 报告 | 读书 | 书单

大数据 | 揭秘 | 人工智能 | AI

Python | 机器学习 | 深度学习 | 神经网络

可视化 | 区块链 | 干货 | 数学


猜你想看




Q: 你还知道哪些处理数据的技巧

欢迎留言与大家分享

觉得不错,请把这篇文章分享给你的朋友

转载 / 投稿请联系:baiyu@hzbook.com

更多精彩,请在后台点击“历史文章”查看

点击阅读原文,了解更多

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存