Pandas数据清洗系列:DataFrame.sample方法详解

从今天开始,我们开始更新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中各个参数的使用:

n

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

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

简单随机抽样可以分为有放回抽样和无放回抽样。有放回抽样中,因为抽到的数据可以放回,因此一个样本数据在一次抽样试验中可能会被抽到多次,无放回抽样只能会被抽到一次。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,原因是相同的。

weights

sample方法中weights参数是一个较难的参数。这个参数是用来指定抽样权重的,权重越大表示该行数据或该列数据被抽到的概率越大。这个参数默认值是None,表示此时执行等概率抽样,也就是说每一行或每一列被抽到的概率相等。我们可以给weights参数传递两种类型数据,一个是str类型,一种是Series类型。

  • 如果是str类型,这个str要求是DataFrame中的一个列名(即执行行抽样)。pandas将str这个列的取值作为该行数据的抽样权重进行抽样。如果列中数据相加和不等于1,该列数据将被标准化到和为1.列中如果有缺失值,该行数据的抽样权重被视为0,也就是说不抽取这一行数据。此外这个列中不允许无限值。例如,我们将示例数据中num_wings列作为抽样权重,num_wings列的四个取值分别为2,0,0,0,四个数据的和为2,不是1,会首先标准化到和为1,也就是最终抽样时,权重为1,0,0,0。这意味着在抽取数据时,后三行数据由于抽样权重为0,因此永远抽不到。
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
  • weights还可以是一个Series。此时Series的长度可以和数据中行或列的长度不同。以行抽样为例子,在进行抽样之前,pandas会先进行索引对齐,相当于对DataFrame和Series做一个左连接。DataFrame没有匹配到的所以对应的行抽样权重为0.我们用例子来说明:
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

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

axis

我们已经说过了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中其他的函数和方法。

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值