【问题标题】:Subsample pandas dataframe子样本熊猫数据框
【发布时间】:2013-09-13 20:50:46
【问题描述】:

我有一个从.tsv 文件加载的DataFrame。我想生成一些探索性的情节。问题是数据集很大(约 100 万行),因此图上的点太多而看不到趋势。另外,绘图需要一段时间。

我想对 10000 个随机分布的行进行子抽样。这应该是可重现的,因此每次运行都会生成相同的随机数序列。

这:Sample two pandas dataframes the same way 似乎在正确的轨道上,但我不能保证子样本的大小。

【问题讨论】:

  • 必须是随机的吗?例如,您也可以采取每千分之一。为什么不能保证子样本的大小?你说你想要一个 10000 的子样本。
  • 是的,我可以每 (1/N) 行进行二次抽样以获得 N 个点。但我想知道如果我们需要随机选择的点,我们该如何解决。另一件事是,如果数据以等于 N 的频率振荡。我最终会在完全相同的点选取数据。
  • 好的,有充分的理由。但是您链接到的解决方案有什么问题?如果您不能保证大小,您可以将random.randint 的大小设置为数据帧长度的某个部分。
  • 如果我正确阅读了解决方案,似乎我无法控制子样本中有多少条记录。因为,我无法控制生成的True 的数量。我想应该有一种方法可以通过使用numpy.random.randint() 而无需替换来生成子样本索引。但我不知道,如何。
  • 啊,是的,我的错。我应该更好地阅读它。看我的回答。

标签: python numpy pandas subsampling


【解决方案1】:

您可以使用np.random.choice 从索引中选择随机元素。例如选择 5 个随机行:

df = pd.DataFrame(np.random.rand(10))

df.loc[np.random.choice(df.index, 5, replace=False)]

此功能是 1.7 中的新功能。如果你想要一个旧 numpy 的解决方案,你可以打乱数据并获取其中的第一个元素:

df.loc[np.random.permutation(df.index)[:5]]

这样,您的 DataFrame 不再排序,但如果绘图需要这样做(例如,线图),您可以在之后简单地执行 .sort()

【讨论】:

  • 谢谢。我意识到我使用了错误的括号 ix = numpy.random.choice(10, size=5, replace=False, p=None)df = train1.loc(ix) :)
【解决方案2】:

如今,人们可以简单地在 DataFrame 上使用 sample 方法:

>>> help(df.sample)
Help on method sample in module pandas.core.generic:

sample(self, n=None, frac=None, replace=False, weights=None, random_state=None, axis=None) method of pandas.core.frame.DataFrame instance
    Returns a random sample of items from an axis of object.

可复制性可以通过使用random_state关键字来实现:

>>> len(set(df.sample(n=1, random_state=np.random.RandomState(0)).iterations.values[0] for _ in xrange(1000)))
1
>>> len(set(df.sample(n=1).iterations.values[0] for _ in xrange(1000)))
40

【讨论】:

  • 知道为什么random_state 参数无法产生可复制性吗?我正在执行多次,每次都使用data = data.sample(n = len(data), random_state = np.random.RandomState(1337)) 获得不同的排序
  • 在花费超过我想承认的时间后发现了我的问题。评论希望将来有人也会卡住。此代码将产生相同的结果:data.sample(n = len(data), random_state = np.random.RandomState(1337)) 但将其设置为新的 DataFrame 不会。请参阅 frac 替换 len 东西和 replace 以清理更多内容。
【解决方案3】:

不幸的是,np.random.choice 对于小样本(不到所有行的 10%)似乎相当慢,您最好使用普通的 ol' 样本:

from random import sample
df.loc[sample(df.index, 1000)]

对于大型 DataFrame(一百万行),我们看到小样本:

In [11]: %timeit df.loc[sample(df.index, 10)]
1000 loops, best of 3: 1.19 ms per loop

In [12]: %timeit df.loc[np.random.choice(df.index, 10, replace=False)]
1 loops, best of 3: 1.36 s per loop

In [13]: %timeit df.loc[np.random.permutation(df.index)[:10]]
1 loops, best of 3: 1.38 s per loop

In [21]: %timeit df.loc[sample(df.index, 1000)]
10 loops, best of 3: 14.5 ms per loop

In [22]: %timeit df.loc[np.random.choice(df.index, 1000, replace=False)]
1 loops, best of 3: 1.28 s per loop    

In [23]: %timeit df.loc[np.random.permutation(df.index)[:1000]]
1 loops, best of 3: 1.3  s per loop

但大约 10% 的结果大致相同:

In [31]: %timeit df.loc[sample(df.index, 100000)]
1 loops, best of 3: 1.63 s per loop

In [32]: %timeit df.loc[np.random.choice(df.index, 100000, replace=False)]
1 loops, best of 3: 1.36 s per loop

In [33]: %timeit df.loc[np.random.permutation(df.index)[:100000]]
1 loops, best of 3: 1.4 s per loop

如果您要对所有内容进行采样(不要使用示例!):

In [41]: %timeit df.loc[sample(df.index, 1000000)]
1 loops, best of 3: 10 s per loop

注意:numpy.random 和 random 都接受一个种子,以重现随机生成的输出。

正如@joris 在 cmets 中指出的那样,选择(无需替换)实际上是 sugar for permutation,因此对于较小的样本来说它是恒定的时间和更慢的速度也就不足为奇了......

【讨论】:

  • 哇,确实很慢。
  • @joris 我发现真正令人惊讶的是,选择似乎并不比排列快!
  • 但这似乎取决于您从总数中进行子采样的比率,因为 numpy 解决方案仅取决于总大小,而不取决于子样本大小。因此,如果子样本变大,则两种解决方案都会获得更多。如果我尝试使用 1/10 的子样本,它们似乎和 random.sample 一样快。
  • @joris 感觉它应该取决于要选择的算法的比率......对于小样本来说选择有多糟糕似乎很疯狂。
  • @AndyHayden 啊哈,choice 的源代码中的这个idx = self.permutation(pop_size)[:size] 澄清了很多:-)
猜你喜欢
  • 1970-01-01
  • 2016-03-28
  • 2020-08-03
  • 1970-01-01
  • 2021-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-31
相关资源
最近更新 更多