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