DataFrame.sample

DataFrame.sample方法主要是用来对DataFrame进行简单随机抽样的。

PS:这里说的是简单随机抽样,表示是不能用来进行系统抽样、分层抽样的。

DataFrame.sample这个方法可以从DataFrame中随机抽取行,也可以随机抽取列,这个方法接收的参数如下:

DataFrame.sample(n=None
, frac=None
, replace=False
, weights=None
, random_state=None
, axis=None)

sample方法的参数不多,只有6个。在详细介绍这6个参数的使用之前,我们先创建一个DataFrame数据:

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

参数解释:

--n  设置抽样数量

sample方法中的第一个参数n是一个int类型的参数,这个参数用来指定随机抽取的样本数目(行数目)或者列数目,默认随机抽取行数据。这个参数不能与frac参数同时使用,而且如果没有指定frac参数,n参数的默认值是1。

print(df.sample())#不指定就随机抽取1行输出

print(df.sample(2))#随机抽取2行输出

输出:
        num_legs  num_wings  num_specimen_seen
falcon         2          2                 10


        num_legs  num_wings  num_specimen_seen
fish           0          0                  8
spider         8          0                  1

--frac   设置抽样比例

frac参数接收一个float类型数据,指定随机抽取行或列的比例,这个参数不能和n参数同时使用。例如,希望随机抽取80%的行数据,可以使用如下代码:(发现是乱序的)

print(df.sample(frac=0.8))
print(df.sample(frac=0.9))
#最后输出的个数为样本数量*frac,采用五舍六入的原则,所以一个样本输出3个,一个输出4个

输出:
        num_legs  num_wings  num_specimen_seen
fish           0          0                  8
dog            4          0                  2
spider         8          0                  1

        num_legs  num_wings  num_specimen_seen
spider         8          0                  1
dog            4          0                  2
falcon         2          2                 10
fish           0          0                  8

--replace   设置是否放回

replace接收一个bool类型数据,False表示执行无放回抽样,True表示执行有放回抽样。默认值为False,即执行无放回抽样。

df.sample(3,replace=True)

输出
        num_legs  num_wings  num_specimen_seen
falcon         2          2                 10
falcon         2          2                 10
fish           0          0                  8

当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

--weights   设置样本权重

这个参数是用来指定抽样权重的,权重越大表示该行数据或该列数据被抽到的概率越大。这个参数默认值是None,表示此时执行等概率抽样,也就是说每一行或每一列被抽到的概率都相等。

可以给weights参数传递两种类型数据,一个是str类型,一种是Series类型。

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

Series

长度可以和数据中行或列的长度不同。以行抽样为例子,在进行抽样之前,pandas会先进行索引对齐,相当于对DataFrame和Series做一个左连接。DataFrame没有匹配到的索引对应的行抽样权重为0。我们用例子来说明:

先创建了一个Series数据,有三个元素,索引分别为falcon,dog,cat,注意到其中一个索引标签cat在我们上面的数据行索引标签中没有找到匹配。接下来我们将s作为抽样权重赋值给weights:

s = pd.Series([0.2,0.5,0.3],index=['falcon','dog','cat'])
df.sample(4,weights=s,replace=True)
输出
        num_legs  num_wings  num_specimen_seen
falcon         2          2                 10
dog            4          0                  2
spider         8          0                  1
fish           0          0                  8

可以这样理解,首先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