2016-05-24 59 views
8

我想从两个数据框中取出样本,其中我需要保持计数的比例。例如Apache spark中的Dataframe示例斯卡拉

df1.count() = 10 
df2.count() = 1000 

noOfSamples = 10 

欲取样以这样的方式,我得到大小101的10个样品的每个(1从DF1和100从DF2)

查阅,而这样做的数据,

var newSample = df1.sample(true, df1.count()/noOfSamples) 
println(newSample.count()) 

这里的分数意味着什么?它可以大于1吗?我检查了thisthis,但无法完全理解它。

还有,无论如何我们可以指定要采样的行数?

回答

14

fraction参数代表将返回的数据集的一部分aproximate。例如,如果将其设置为0.1,则将返回10%(1/10)的行。对于你的情况,我相信要做到以下几点:

val newSample = df1.sample(true, 1D*noOfSamples/df1.count) 

但是,您可能会注意到newSample.count将每次运行时返回不同数量的,这是因为fraction将是一个随机的阈 - 生成的值(如您所见here),因此生成的数据集大小可能会有所不同。一个解决方法可以是:

val newSample = df1.sample(true, 2D*noOfSamples/df1.count).limit(df1.count/noOfSamples) 

一定的可扩展性意见

你可能注意到,因为它计算整个数据框一个df1.count可能是昂贵的,你会失去的好处之一首先取样。

因此,根据您的应用环境,您可能希望使用已知已知总样本数或近似值。

val newSample = df1.sample(true, 1D*noOfSamples/knownNoOfSamples) 

或者假设你数据框的大小为巨大的,我仍然会用一个fraction和使用limit强制采样的数量。

val guessedFraction = 0.1 
val newSample = df1.sample(true, guessedFraction).limit(noOfSamples) 

至于你的问题:

可以在大于1?

不是。它代表一个分数,所以它必须是介于0和1之间的一个十进制数。如果将其设置为1,它将带来100%的行,因此设置它是没有意义的到一个大于1的数字。

还有无论如何我们可以指定要采样的行数?

您可以指定比想要的行数更大的部分,然后使用限制,如我在第二个示例中所示。也许有另一种方式,但这是我使用的方法。

+0

虽然它对我来说更清晰,但是您提出的解决方案可能无法在当前场景中使用(请参阅编辑)。 df2.sample(true,noOfSample/df2.count).limit(df2.count/noOfSamples)会给我1%的数据,即10行,这将少于我需要的100行。对此有何想法? – hbabbar

+1

@hbabbar所以你总是需要每个数据集的10%?如果是这样,你可以做'df2.sample(true,0.15).limit(0.1 * df2.count)' –

-1

可能是你想尝试下面的代码..

val splits = data.randomSplit(Array(0.7, 0.3)) 
val (trainingData, testData) = (splits(0), splits(1)) 
3

要回答如果分数可以大于1。是的,它可以是如果我们更换为是。如果提供的值大于1,则替换为false,则会发生以下异常:

java.lang.IllegalArgumentException: requirement failed: Upper bound (2.0) must be <= 1.0. 
2

我也发现样本的计数功能缺乏干扰。如果你不挑剔创建一个临时的看法,我觉得以下有用的代码(DF是你的数据帧,计数样本大小):

val tableName = s"table_to_sample_${System.currentTimeMillis}" 
df.createOrReplaceTempView(tableName) 
val sampled = sqlContext.sql(s"select *, rand() as random from ${tableName} order by random limit ${count}") 
sqlContext.dropTempTable(tableName) 
sampled.drop("random") 

它,只要你的当前行数是一样大返回精确计数作为你的样本量。

+0

如果我没有弄错,你可以用DataFrame API完成同样的查询,不需要创建临时视图并使用SQL查询。但是,这会触发排序操作,我相信它会比使用示例慢很多。 –