カウントの比率を維持する必要がある2つのデータフレームからサンプルを取り出そうとしています。例えば
df1.count() = 10
df2.count() = 1000
noOfSamples = 10
私はそれぞれサイズ101の10個のサンプルを取得するようにデータをサンプリングしたい(df1から1個、df2から100個)
今そうしながら、
var newSample = df1.sample(true, df1.count() / noOfSamples)
println(newSample.count())
ここの分数は何を意味していますか? 1より大きくできますか? this および this をチェックしましたが、完全に理解することができませんでした。
とにかくサンプリングする行数を指定できるのでしょうか?
fraction
パラメーターは、返されるデータセットのaproximate割合を表します。たとえば、0.1
に設定すると、行の10%(1/10)が返されます。あなたの場合、次のことをしたいと考えています。
val newSample = df1.sample(true, 1D*noOfSamples/df1.count)
ただし、newSample.count
は実行するたびに異なる数値を返すことに気付く場合があります。これは、fraction
がランダムに生成された値のしきい値になるためです(ご覧のとおり ここ )であるため、結果のデータセットサイズは異なる場合があります。回避策は次のとおりです。
val newSample = df1.sample(true, 2D*noOfSamples/df1.count).limit(df1.count/noOfSamples)
いくつかのスケーラビリティの観察
df1.count
を実行すると、DataFrame全体を評価するため、コストがかかる場合があります。そもそもサンプリングの利点の1つが失われることに注意してください。
したがって、アプリケーションのコンテキストに応じて、すでに既知の合計サンプル数または近似値を使用することができます。
val newSample = df1.sample(true, 1D*noOfSamples/knownNoOfSamples)
または、DataFrameのサイズを非常に大きいと仮定して、fraction
を使用し、limit
を使用してサンプル数を強制します。
val guessedFraction = 0.1
val newSample = df1.sample(true, guessedFraction).limit(noOfSamples)
質問に関して:
1より大きくできますか?
いいえ。0〜1の小数部を表します。1に設定すると、行の100%がもたらされるため、1より大きい数値に設定しても意味がありません。
とにかくサンプリングする行数を指定できるのでしょうか?
2番目の例で示すように、必要な行数よりも大きな割合を指定してから、limitを使用できます。別の方法があるかもしれませんが、これは私が使用するアプローチです。
分数が1より大きくなる可能性がある場合に答えるにはい。 replace falseで1より大きい値を指定すると、次の例外が発生します。
Java.lang.IllegalArgumentException: requirement failed: Upper bound (2.0) must be <= 1.0.
私も、機能を妨害することでサンプルの不足を見つけました。一時ビューの作成について気に入らない場合は、以下のコードが役立ちます(dfはデータフレーム、countはサンプルサイズです):
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")
現在の行数がサンプルサイズと同じである限り、正確な数を返します。
あなたの質問に答えるために、とにかくサンプリングする行の数を指定できますか?
最近、sparkデータフレームから特定の行数をサンプリングする必要がありました。以下のプロセスに従いました。
sparkデータフレームをrddに変換します。例:_df_test.rdd
_
RDDにはtakeSampleという機能があり、必要なサンプル数をシード番号で指定できます。例:df_test.rdd.takeSample(withReplacement, Number of Samples, Seed)
sqlContext.createDataFrame()
を使用してRDDをsparkデータフレームに戻す
単一のステップに結合された上記のプロセス:
サンプルする必要があるデータフレーム(または母集団)には約8,000レコードがあります:df_grp_1
_df_grp_1
test1 = sqlContext.createDataFrame(df_grp_1.rdd.takeSample(False,125,seed=115))
_
test1データフレームには、125個のサンプルレコードがあります。
以下のコードは、データフレームdfの70%と30%のランダムな分割を行う場合に機能します。
val Array(trainingDF, testDF) = df.randomSplit(Array(0.7, 0.3), seed = 12345)
正確な数のレコードが望ましい場合、この関数をランダムサンプリングに使用します。
def row_count_sample (df, row_count, with_replacement=False, random_seed=113170):
ratio = 1.08 * float(row_count) / df.count() # random-sample more as dataframe.sample() is not a guaranteed to give exact record count
# it could be more or less actual number of records returned by df.sample()
if ratio>1.0:
ratio = 1.0
result_df = (df
.sample(with_replacement, ratio, random_seed)
.limit(row_count) # since we oversampled, make exact row count here
)
return result_df