【问题标题】:Sampling from MultiIndex DataFrame从 MultiIndex DataFrame 采样
【发布时间】:2016-01-20 01:53:17
【问题描述】:

我正在使用名为 df_dataMultiIndex 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.samplefunction,但我似乎无法处理面板中的特定多级索引。 我可以编写各种循环来完成这项工作,但我认为应该有一种更简单(更快)的方法来做到这一点。 我在 Python 3.5 上,我使用的是 pandas 0.17.1 版。 谢谢。

【问题讨论】:

标签: python pandas dataframe sampling


【解决方案1】:

一个简单的解决方案:

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

【讨论】:

  • 由于使用了subindex.isin(sample_ids),我不清楚这是否会多次采样?
【解决方案2】:

您可以使用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

如果你想要一个独特的sampleindex,你可以添加:

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)

【讨论】:

  • 嗨 Stefan,这是一个很好的解决方案,比我昨晚做的快 30 倍。要添加到您的解决方案中的一件事是重新索引示例,以便索引再次唯一,并且可以在其上运行一些 pandas 函数(如 OLS 等)。像这样的东西:individualsb = list(range(100))indexb = pd.MultiIndex.from_tuples(list(product(individualsb, time)))sample = sample.set_index(indexb)
  • 不客气,更新以摆脱 MultiIndex 中的骗子。
【解决方案3】:

这对我有用,它是其他答案的一种组合:

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 及其所有相关“其他”的样本。

【讨论】:

  • 请注意,这不会按照问题的要求实现带替换抽样
猜你喜欢
  • 2018-01-20
  • 1970-01-01
  • 2013-03-25
  • 1970-01-01
  • 2017-09-19
  • 2019-02-08
  • 2013-03-15
  • 2020-08-14
  • 2021-08-21
相关资源
最近更新 更多