如何从PySpark DataFrame获取随机行?

Dan*_*anT 18 python dataframe apache-spark apache-spark-sql pyspark

如何从PySpark DataFrame中获取随机行?我只看到sample()以分数作为参数的方法.将此分数设置1/numberOfRows为随机结果,有时我不会得到任何行.

On RRD有一个方法takeSample(),它将您希望样本包含的元素数作为参数.我知道这可能很慢,因为你必须计算每个分区,但有没有办法在DataFrame上得到这样的东西?

zer*_*323 44

你可以简单地打电话takeSampleRDD:

df = sqlContext.createDataFrame(
    [(1, "a"), (2, "b"), (3, "c"), (4, "d")], ("k", "v"))
df.rdd.takeSample(False, 1, seed=0)
## [Row(k=3, v='c')]
Run Code Online (Sandbox Code Playgroud)

如果你不想收集,你可以简单地采取更高的分数和限制:

df.sample(False, 0.1, seed=0).limit(1)
Run Code Online (Sandbox Code Playgroud)

  • 不要传递`seed`,每次都应该得到一个不同的DataFrame。 (4认同)
  • 哦,因为“collect”[将其返回给驱动程序](/sf/ask/3092232321/),它可能不适合驱动程序的内存。 (4认同)
  • 有没有办法获得随机值。在上述情况下,每次运行查询时都会生成相同的数据帧。 (2认同)
  • 我不认为第二个样本 -> 极限解是相当随机的。样本()部分是好的和随机的,但结果似乎在采取限制之前进行了某种排序。如果您使用 limit(10) 而不是 1 并且您的分数太大,则这一点尤其明显。结果可能看起来相似。 (2认同)

小智 7

不同类型的样品

随机抽样 % 有替换和无替换的数据

import pyspark.sql.functions as F
#Randomly sample 50% of the data without replacement
sample1 = df.sample(False, 0.5, seed=0)

#Randomly sample 50% of the data with replacement
sample1 = df.sample(True, 0.5, seed=0)

#Take another sample exlcuding records from previous sample using Anti Join
sample2 = df.join(sample1, on='ID', how='left_anti').sample(False, 0.5, seed=0)

#Take another sample exlcuding records from previous sample using Where
sample1_ids = [row['ID'] for row in sample1.ID]
sample2 = df.where(~F.col('ID').isin(sample1_ids)).sample(False, 0.5, seed=0)

#Generate a startfied sample of the data across column(s)
#Sampling is probabilistic and thus cannot guarantee an exact number of rows
fractions = {
        'NJ': 0.5, #Take about 50% of records where state = NJ
    'NY': 0.25, #Take about 25% of records where state = NY
    'VA': 0.1, #Take about 10% of records where state = VA
}
stratified_sample = df.sampleBy(F.col('state'), fractions, seed=0)
Run Code Online (Sandbox Code Playgroud)