我正在尝试在Pandas中实现Block Bootstrapping。
例如,假设我的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
尤其是,DataFame在month
,personid
处是唯一的,实际上包含许多行,其中每个personid
与不同的月份关联。
我想在personid
级别实现“块引导”。也就是说,我想从personid
中所有唯一值的集合中进行替换采样,然后从该采样中返回一个DataFrame,其中包含所有相关的month
和value
列。 / p>
例如,我有这样的东西:
personids = df.personid.unique()
在这种情况下会导致
array([1, 2, 3])
然后,我将替换样品:
np.random.choice(personids, size=personids.size, replace=True)
在这种情况下,这可能会导致:
array([3, 3, 2])
因此,现在,如果是得到的采样,我想要一个自举数据框,将其命名为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
到目前为止,我这样做的方式是:
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
该函数的基本作用是循环遍历采样的Personid向量,并将原始Data Frame的子集提取出每个Personid。然后将所有内容结合在一起。恐怕这效率很低。有更好的方法吗?
答案 0 :(得分:2)
实际上,我只是想出一种非常简单的方法来做到这一点。如果我将personid
设置为索引,则可以按索引将DataFrame子集化,它将完成我想要的事情。
例如,如果我这样做:
sampled_personids = np.random.choice(personids, size=personids.size, replace=True)
那让我失望
array([1, 2, 2])
然后,如果我这样做:
df.loc[sampled_personids]
我得到:
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
答案 1 :(得分:0)
您可以使用merge
。首先使用随机的bootstrapped_df
创建一个personids
:
bootstrapped_df = pd.DataFrame({'personid':np.random.choice( personids, size=personids.size,
replace=True)})
对我来说是
personid
0 2
1 1
2 1
然后将merge
与参数how='left'
一起使用:
bootstrapped_df = bootstrapped_df.merge(df,how='left')
我得到bootstrapped_df
:
personid month values
0 2 Aug 400
1 2 Sep 500
2 1 Jan 100
3 1 Feb 200
4 1 Mar 300
5 1 Jan 100
6 1 Feb 200
7 1 Mar 300
编辑您可以在一行中完成所有操作:
bootstrapped_df = (pd.DataFrame({'personid':np.random.choice( personids, size=personids.size,
replace=True)})
.merge(df,how='left'))