赞
踩
从今天开始,我们开始更新pandas数据清洗系列。今天我们来学习pandas中的DataFrame.sample方法。pandas数据清洗系列开篇先介绍这个方法并没有什么特殊含义,主要是因为今天工作中刚好用到了这个方法。现在只不过是趁热打铁,将其整理成文而已。简单地说,DataFrame.sample方法主要是用来对DataFrame进行简单随机抽样的。注意,这里说的是简单随机抽样,标识DataFrame.sample是不能用来进行系统抽样、分层抽样的。DataFrame.sample这个方法可以从DataFrame中随机抽取行,也可以随机抽取列,接下来我们就来学习一下。这个方法接收的参数如下:
DataFrame.sample(n=None
,frac=None
,replace=False
,weights=None
,random_state=None
,axis=None)
sample方法的参数不多,只有6个。在详细介绍这6个参数的使用之前,我们就先创建一个DataFrame数据:
import padas as pd
df = pd.DataFrame({'num_legs':[2,4,8,0],
'num_wings':[2,0,0,0],
'num_specimen_seen':[10,2,1,8]},
index = ['falcon','dog','spider','fish'])
print(df)
>>>
num_legs num_wings num_specimen_seen
falcon 2 2 10
dog 4 0 2
spider 8 0 1
fish 0 0 8
我们创建了一个4行3列的数据,并为行指定了一个索引。接下来我们详细介绍sample中各个参数的使用:
sample方法中的额第一个参数n是一个int类型的参数,这个参数用来指定随机抽取的样本数据(行数目)或者列数目,默认随机抽取行数据。这个参数不能与frac参数同时使用,而且如果没有在指定frac参数,n参数的默认值是1。
df.sample(2)
>>>
num_legs num_wings num_specimen_seen
spider 8 0 1
fish 0 0 8
不指定n,也不指定frac时,默认随机抽取一行数据。
df.sample()
>>>
num_legs num_wings num_specimen_seen
dog 4 0 2
frac参数接收一个float类型数据,指定随机抽取行或列的比例,这个参数不能和n参数同时使用。例如,我们希望随机抽取80%的行数据,可以使用如下代码:
df.sample(frac=0.8)
>>>
num_legs num_wings num_specimen_seen
dog 4 0 2
fish 0 0 8
spider 8 0 1
原始数据有4行,4*0.8=3.2,看来是舍去了小数,所以结果返回了3行数据。如果随机抽取90%的数据呢
df.sample(frac=0.9)
>>>
num_legs num_wings num_specimen_seen
spider 8 0 1
dog 4 0 2
fish 0 0 8
falcon 2 2 10
40.9=3.6,如果是舍去小数部分,应该返回3行数据才对,现在返回的是4行数据。事实上pandas在处理抽样数目时,采用的是五舍六入的原则。例如我们制定抽取40.85=3.5条数据时,返回的还是3条数据:
df.sample(frac=0.85)
>>>
num_legs num_wings num_specimen_seen
dog 4 0 2
falcon 2 2 10
fish 0 0 8
在官方文档中并没有限定frac参数必须接收0~1之间的数,这暗示frac可以接收大于1的浮点数,这时其实执行的是unsampling。frac如果接收了大于1的浮点数,需要对replace参数进行设置,接下来我们看一下replace这个参数。
简单随机抽样可以分为有放回抽样和无放回抽样。有放回抽样中,因为抽到的数据可以放回,因此一个样本数据在一次抽样试验中可能会被抽到多次,无放回抽样只能会被抽到一次。replace接收一个bool类型数据,False表示执行无放回抽样,True表示执行有放回抽样。默认值为False,即执行无放回抽样。
df.sample(3,replce=True
>>>
num_legs num_wings num_specimen_seen
falcon 2 2 10
falcon 2 2 10
fish 0 0 8
可以看到,replace指定为True时,索引为falcon的数据被抽到了两次。
当frac接收大于1的浮点数,这意味着sample方法返回的样本量大于原始数据的样本量,只有有放回抽样才能做到这一点,因此此时replace参数必须指定为True:
df.sample(frac=1.5,replace=True)
>>>
num_legs num_wings num_specimen_seen
spider 8 0 1
dog 4 0 2
dog 4 0 2
spider 8 0 1
dog 4 0 2
dog 4 0 2
当参数n指定的数目大于样本数目时,也需要指定replace=True,原因是相同的。
sample方法中weights参数是一个较难的参数。这个参数是用来指定抽样权重的,权重越大表示该行数据或该列数据被抽到的概率越大。这个参数默认值是None,表示此时执行等概率抽样,也就是说每一行或每一列被抽到的概率相等。我们可以给weights参数传递两种类型数据,一个是str类型,一种是Series类型。
df.sample(4,weights='num_wings',replace=True)
>>>
num_legs num_wings num_specimen_seen
falcon 2 2 10
falcon 2 2 10
falcon 2 2 10
falcon 2 2 10
s = pd.Series([0.2,0.5,0.3],index=['falcon','dog','cat']
我们先创建了一个Series数据,有三个元素,索引分别为falcon,dog,cat,注意到其中一个所以标签cat在我们上面的数据行索引标签中没有找到匹配。接下来我们将s作为抽样权重赋值为weights:
df.sample(4,weights=s,replace=True)
>>>
num_legs num_wings num_specimen_seen
dog 4 0 2
dog 4 0 2
falcon 2 2 10
dog 4 0 2
返回什么结果不重要,重要的是理解背后的机制。我们可以这样理解,首先pandas将df和s进行左连接,df为左表,s为右表。会返回如下结果:
num_legs num_wings num_specimen_seen weights
falcon 2 2 10 0.2
dog 4 0 2 0.5
spider 8 0 1 nan
fish 0 0 8 nan
可以看到从s中,df中的第一行和第二行数据匹配到样本权重,分别为0.2和0.5,而第三行和第四行数据没有匹配到抽样权重,因此为缺失值。接下来按照weights的数据作为权重进行抽样,由于后两行weights均为缺失值,也就是抽样权重为0,因此在抽样时将排除这两行。即有效的行为:
num_legs num_wings num_specimen_seen weights
falcon 2 2 10 0.2
dog 4 0 2 0.5
由于这两行数据的抽样权重分别为0.2和0.5,和为0.7不为1,在抽样前会标准化到和为1,最终两行的抽样权重分别为0.285和0.715,也就是说第一行有28.5%的概率被抽到,而第二行有71.5%的概率被抽到,因此出现上述结果。
random_state这个参数可以复现抽样结果,比如说,今天你在一个数据集上进行了抽样,明天在同一个数据上抽样时,你希望得到和今天同样的抽样结果,就可以使用这个参数。这个参数接收一个int类型。
第一次抽样,随机抽取一个样本:
df.sample(random_state=1)
>>>
num_legs num_wings num_specimen_seen
fish 0 0 8
第二次抽样,希望得到同样的结果,可以指定相同的random_state
df.sample(random_state=1)
>>>
num_legs num_wings num_specimen_seen
fish 0 0 8
不指定random_state时,返回的可能就是不同值了
df.sample()
>>>
num_legs num_wings num_specimen_seen
spider 8 0 1
我们已经说过了sample方法可以对行进行抽样,也可以对列进行抽样。控制这一行为的参数就是axis。当axis指定为0或者‘index’时,对行进行抽样,当axis指定为1或者‘col’时,对列进行抽样。默认执行的是行抽样。
#行抽样 df.sample(axis=0) >>> num_legs num_wings num_specimen_seen spider 8 0 1 #行抽样 df.sample(axis='index') >>> num_legs num_wings num_specimen_seen fish 0 0 8 #列抽样 df.sample(axis=1) >>> num_legs falcon 2 dog 4 spider 8 fish 0 #列抽样 df.sample(axis='columns') >>> num_specimen_seen falcon 10 dog 2 spider 1 fish 8
sample方法使用起来还是比较简单的,这仅仅是pandas数据清洗这个系列的一道开胃菜,接下来,我们会逐步更新pandas中其他的函数和方法。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。