子采样熊猫数据帧



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

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

这:以相同的方式对两个熊猫数据帧进行采样似乎在正确的轨道上,但我不能保证子样本大小。

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

这样,您的数据帧将不再排序,但如果绘图(例如,线图)需要排序,则只需在之后执行.sort()即可。

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

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

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

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在评论中指出的那样,选择(没有替换)实际上是排列的糖,所以对于较小的样本来说,它是恒定的时间和更慢的时间也就不足为奇了......

如今,人们可以简单地在数据帧上使用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

最新更新