簡體   English   中英

使用 pyspark/spark 對大型分布式數據集進行采樣

[英]Sampling a large distributed data set using pyspark / spark

我在 hdfs 中有一個文件,它分布在集群中的節點上。

我正在嘗試從此文件中獲取 10 行的隨機樣本。

在 pyspark shell 中,我使用以下命令將文件讀入 RDD:

>>> textFile = sc.textFile("/user/data/myfiles/*")

然后我想簡單地做一個樣本......關於 Spark 很酷的事情是有像takeSample這樣的命令,不幸的是我認為我做錯了什么,因為以下需要很長時間:

>>> textFile.takeSample(False, 10, 12345)

所以我嘗試在每個節點上創建一個分區,然后使用以下命令指示每個節點對該分區進行采樣:

>>> textFile.partitionBy(4).mapPartitions(lambda blockOfLines: blockOfLines.takeSample(False, 10, 1234)).first()

但這會產生錯誤ValueError: too many values to unpack

org.apache.spark.api.python.PythonException: Traceback (most recent call last):
  File "/opt/cloudera/parcels/CDH-5.0.2-1.cdh5.0.2.p0.13/lib/spark/python/pyspark/worker.py", line 77, in main
    serializer.dump_stream(func(split_index, iterator), outfile)
  File "/opt/cloudera/parcels/CDH-5.0.2-1.cdh5.0.2.p0.13/lib/spark/python/pyspark/serializers.py", line 117, in dump_stream
    for obj in iterator:
  File "/opt/cloudera/parcels/CDH-5.0.2-1.cdh5.0.2.p0.13/lib/spark/python/pyspark/rdd.py", line 821, in add_shuffle_key
    for (k, v) in iterator:
ValueError: too many values to unpack

如何使用 spark 或 pyspark 從大型分布式數據集中采樣 10 行?

嘗試使用textFile.sample(false,fraction,seed)代替。 takeSample通常會很慢,因為它在 RDD 上調用count() 它需要這樣做,因為否則它不會從每個分區中均勻獲取,基本上它使用計數以及您要求的樣本大小來計算分數並在內部調用sample sample很快,因為它只使用一個隨機布爾生成器,該生成器在時間的百分比中返回真實的fraction ,因此不需要調用count

此外,我認為這不會發生在你身上,但如果返回的樣本量不夠大,它會再次調用sample ,這顯然會減慢它的速度。 由於您應該對數據的大小有所了解,因此我建議您調用 sample,然后自己將樣本縮小到大小,因為您對數據的了解比 spark 多。

使用 sample 而不是 takeSample 似乎可以讓事情變得相當快:

textFile.sample(False, .0001, 12345)

這樣做的問題是,除非您對數據集中的行數有一個大致的了解,否則很難知道要選擇的正確分數。

PySpark 中不同類型的樣本

隨機抽樣 % 有替換和無替換的數據

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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM