从MultiIndex DataFrame中进行抽样

9

我正在使用名为df_data的pandas DataFrame中的以下面板数据:

              y         x
n   time                    
0   0     0.423607 -0.307983
    1     0.565563 -0.333430
    2     0.735979 -0.453137
    3     0.962857  1.671106
1   0     0.772304  1.221366
    1     0.455327 -1.024852
    2     0.864768  0.609867
    3     0.334429 -2.567936
2   0     0.435553 -0.259228
    1     0.221501  0.484677
    2     0.773628  0.650288
    3     0.293902  0.566452

n索引一个个体(共500个),t索引时间。这是一个平衡面板数据。我想创建一个有放回的随机样本,包括nn=100个个体。另外,如果一个个体进入了随机样本,那么该个体的所有4个时间观测(t=0,1,2,3)都应该分配给样本。

下面这行代码几乎满足我的需求:

df_sample = df_data.loc[np.random.randint(3, size=100).tolist()]

然而,它不会重复抽样个体。所以如果随机变量的列表是 [2, 3, 2, 4, 1, ...] ,那么第三个个体 (索引=2 是第三个个体) 只被选取一次而不是两次进入随机样本。这意味着只要上述随机向量包含同一个个体超过一次,我最终会得到少于100个个体(每个个体有4次观察结果)的随机样本。 我还尝试了 df_data.sample 函数,但它似乎不能处理我这里在面板中具有特定多级索引的情况。 我可以写各种循环来完成这个任务,但我认为应该有一种更简单(并且更快)的方法来完成这个任务。 我使用 Python 3.5,并且使用 pandas 版本 0.17.1。 谢谢。

3个回答

5

一个简单的解决方案:

subindex = df.index.get_level_values('sub_index')
sample_ids = np.random.choice(subindex, 5, replace=True)
sample = df[subindex.isin(sample_ids)].copy()

1
对我来说不太清楚,如果使用 subindex.isin(sample_ids),是否会进行多次抽样? - Michael Oberst

4
您可以使用 itertools.product 快速生成所需格式,以从 MultiIndex 中选择重复项:

样本数据:

from itertools import product
individuals = list(range(500))
time = (0, 1, 2, 3,)
index = pd.MultiIndex.from_tuples(list(product(individuals, time)))
df = pd.DataFrame(data={'A': np.random.random(size=2000), 'B': np.random.random(size=2000)}, index=index)

              A         B
0   0  0.208461  0.842118
    1  0.481681  0.096121
    2  0.420538  0.922363
    3  0.859182  0.078940
1   0  0.171162  0.255883
    1  0.338864  0.975492
    2  0.270533  0.504605
    3  0.691041  0.709189
2   0  0.220405  0.925001
    1  0.811951  0.479795
    2  0.010527  0.534866
    3  0.561204  0.915972
3   0  0.813726  0.083478
    1  0.745100  0.462120
    2  0.189111  0.552039
    3  0.006141  0.622969

使用 productnp.random.randint的结果与 time 值组合起来:

sample_ix = np.random.randint(low=0, high=500, size=100)

len(np.unique(sample_ix))

91

sample_multi_ix = list(product(sample_ix, time))

[(55, 0), (55, 1), (55, 2), (55, 3), (254, 0), (254, 1), (254, 2), (254, 3), ...]

并相应地进行选择:

sample = df.loc[sample_multi_ix, :]
sample.info()

MultiIndex: 400 entries, (55, 0) to (135, 3)
Data columns (total 2 columns):
A    400 non-null float64
B    400 non-null float64
dtypes: float64(2)
memory usage: 9.4+ KB

如果您想要一个独一无二的样本索引,可以添加以下内容:
sample.index = pd.MultiIndex.from_tuples(list(product(list(range(100)), time))) 

MultiIndex: 400 entries, (0, 0) to (99, 3)
Data columns (total 2 columns):
A    400 non-null float64
B    400 non-null float64
dtypes: float64(2)

1
嗨,Stefan,这是一个很好的解决方案,比我昨晚想出来的快了大约30倍。你的解决方案需要添加一件事情,就是重新索引样本,使索引再次唯一,并且可以在其中运行一些pandas函数(如OLS等)。像这样: individualsb = list(range(100))indexb = pd.MultiIndex.from_tuples(list(product(individualsb, time)))sample = sample.set_index(indexb) - J Jung
1
不客气,已更新以消除“MultiIndex”中的重复项。 - Stefan

2

这对我有用,它有点是其他答案的结合:

subindex = df.index.get_level_values('id')
sample_ids = np.random.choice(subindex, 5, replace=False)
sample = df.loc[sample_ids]

我使用了一个索引为["id", "other"]的数据框df。它返回了5个id及其所有相关的“others”的样本。


1
请注意,这并没有按照问题要求实现替换抽样。 - Michael Oberst

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接