2016-05-24 57 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查詢。但是,這會觸發排序操作,我相信它會比使用示例慢很多。 –