专栏首页华章科技用Python玩转统计数据:取样、计算相关性、拆分训练模型和测试

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

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

本文使用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
25% 2.000000
50% 3.000000
75% 4.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': [2, 3, 4]} },
{'_id': 0, 'zip': 1, 'city': 1, 'price': 1, 'beds': 1, 'sq__ft': 1}
)
)
)
# 取样
sample = pd.DataFrame()
for bed in [2, 3, 4]:
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

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

本文分享自微信公众号 - 大数据(hzdashuju)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-12-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 升值加薪Excel神助攻,数据透视表堪称神器!

    VLOOKUP、数据透视表、条件格式…你用这几个技巧做,80%的工作需求都能解决。今天特意整理了这些操作技巧,拯救同在“表海”中挣扎的你,让你的工作效率超乎想...

    华章科技
  • 如何真正学好数据科学?

    作为一个全新的领域,数据科学的飞速发展让人激动。数据科学在带来巨大经济效益的同时,人们在数据科学技术方面的知识沟也逐渐出现,这意味着更多的人需要试图了解和学习数...

    华章科技
  • 【浅观】天文中的那些大数据

    大数据是领域相关的,如今大数据在各个领域都有着卓越的表现。比如,苏州政府、中石油等都使用大数据魔镜——免费的大数据可视化分析工具对自己领域的大数据进行了分析与挖...

    华章科技
  • 并发问题的两种解决方法

    悲观锁: 对关键数据的查询 进行加锁。 (select * from df_goods_sku where id = 17 for update;)

    lesM10
  • 数据为桥迈向智能,渤海财险数据架构智能化演进

    Gartner的报告宣称,到2020年,将近50%的企业将会在业务和IT运维方面采用AIOps。尽管AIOps对于广大运维人员来说,仍然是一个新词,但在各企业已...

    数据和云
  • ESP8266透传:利用STM32f103zet6发送数据到HTTP服务器

    关于ESP8266,网上的程序控制例程也很多,这里就不详细写出来。这节我们来写写怎么编写一个应用程序,打包HTTP格式的数据并传递到HTTP服务器,定义...

    morixinguan
  • 浅谈协程

    如果了解一些操作系统的相关知识的话,我们应该知道:进程是资源分配的最小单位,线程是CPU调度的最小单位。

    windealli
  • ActiveMQ的安装与使用。

    4、ActiveMQ的安装。官方网址:http://activemq.apache.org/

    别先生
  • 消息队列中间件(二)使用 ActiveMQ

    Active MQ 是由 Apache 出品的一款流行的功能强大的开源消息中间件,它速度快,支持跨语言的客户端,具有易于使用的企业集成模式和许多的高级功能,同时...

    未读代码
  • 【HDU 4614】Vases and Flowers(线段树区间更新懒惰标记)

    题目 0到n-1的花瓶,操作1在下标a开始插b朵花,输出始末下标。操作2清空[a,b]的花瓶,求清除的花的数量。 线段树懒惰标记来更新区间。 操作1,先查询0到...

    饶文津

扫码关注云+社区

领取腾讯云代金券