Pandas 中的块引导采样

Vin*_*ent 7 python pandas

我正在尝试在 Pandas 中实现块引导。

例如,假设我的 DataFrame 看起来像这样:

df = pd.DataFrame({
    'personid': [1, 1, 1, 2, 2, 3, 3, 3, 3],
    'month': ['Jan', 'Feb', 'Mar', 'Aug', 'Sep', 'Mar', 'Apr', 'May', 'Jun'],
    'values': [100, 200, 300, 400, 500, 600, 700, 800, 900],
})

df
     month  personid value
0    Jan    1        100
1    Feb    1        200
2    Mar    1        300
3    Aug    2        400
4    Sep    2        500
5    Mar    3        600
6    Apr    3        700
7    May    3        800
8    Jun    3        900
Run Code Online (Sandbox Code Playgroud)

特别是,DataFame 在 处是唯一的monthpersonid并且实际上包含许多行,其中每行personid与不同的月份数相关联。

我想在该级别实现“块引导” personid。也就是说,我想从所有唯一值的集合中进行替换采样personid,然后从该样本中返回一个带有所有关联monthvalue列的 DataFrame。

例如,我有这样的东西:

personids = df.personid.unique()
Run Code Online (Sandbox Code Playgroud)

在这种情况下会导致

 array([1, 2, 3])
Run Code Online (Sandbox Code Playgroud)

然后,我将进行替换采样:

np.random.choice(personids, size=personids.size, replace=True)
Run Code Online (Sandbox Code Playgroud)

在这种情况下,可能会导致:

array([3, 3, 2])
Run Code Online (Sandbox Code Playgroud)

所以现在,如果这就是结果的采样,我想要一个引导数据帧,将其称为bootstrapped_df等于bootstrapped_df

     month  personid value
0    Mar    3        600
1    Apr    3        700
2    May    3        800
3    Jun    3        900
4    Mar    3        600
5    Apr    3        700
6    May    3        800
7    Jun    3        900
8    Aug    2        400
9    Sep    2        500
Run Code Online (Sandbox Code Playgroud)

到目前为止我所做的方法是这样的:

def create_bootstrapped_df(df, sampled_personids):
    """
    Create "Block" Bootstrapped DataFrame given a vector of sampled_personids

    Keyword Args:
        df: DataFrame containing cost data at the personid, month level
        sampled_personids: A vector of personids that is already sampled with replacement.
    """
    bootstrapped = []
    for person in sampled_personids:
        person_df = df.loc[df.personid == person]
        bootstrapped.append(person_df)
    bootstrapped_sample = pd.concat(bootstrapped)
    bootstrapped_sample.reset_index(drop=True, inplace=True)
    return bootstrapped_sample
Run Code Online (Sandbox Code Playgroud)

基本上,该函数的作用是循环遍历采样的 personid 向量,并对原始数据帧进行子集化,取出每个 personid。然后它将所有内容连接在一起。恐怕这样效率很低。有一个更好的方法吗?

Vin*_*ent 6

事实上,我只是想出了一个非常简单的方法来做到这一点。如果我设置personid为索引,那么我可以按索引对 DataFrame 进行子集化,它将执行我想要的操作。

例如,如果我这样做:

sampled_personids = np.random.choice(personids, size=personids.size, replace=True)
Run Code Online (Sandbox Code Playgroud)

这让我

array([1, 2, 2])
Run Code Online (Sandbox Code Playgroud)

然后如果我这样做:

df.loc[sampled_personids]
Run Code Online (Sandbox Code Playgroud)

我得到:

          month personid value
personid
1         Jan   1        100
1         Feb   1        200
1         Mar   1        300
2         Aug   2        400
2         Sep   2        500
2         Aug   2        400
2         Sep   2        500
Run Code Online (Sandbox Code Playgroud)