基於Python+Spark分佈式數據操作:求精確中位數並驗證

基於Python+Spark分佈式數據操作:求精確中位數並驗證

Problem Restatement:

  • 生成1萬個隨機數,存儲在HDFS文件系統中的data1.txt中,每個數字之間用“,”分隔。在Spark平臺上實現如下的功能:
  1. 從HDFS上讀入data1.txt,生成RDD;
  2. 找到這個數據集合的中位數(精確的);
  3. 只能使用RDD有關API,並且不能調用Spark提供的中位數計算的API;
  4. 在Spark平臺上實現中位數算法後,驗證結果的正確性。

Data Generating

generator.py

  • 根據要求生成數據:限定數據量N = 10000,數據範圍爲M = 100,即-50~+50
  • 打開輸出文件
filename = ".\data1.txt"
with open(filename, "w", encoding="utf-8") as file:
	...
  • 導入random庫,使用random.random()生成0~1的數據,轉換爲指定範圍
  • 用’,‘分隔,並保留6位小數’
for i in range(N):
	if i != 0:
		file.write(",")
	file.write(str(round((random.random() - 0.5) * M, 6)))

Preliminary

work.ipynb

  • 生成scspark對象
from pyspark import SparkConf, SparkContext
from pyspark.sql import SparkSession
from pyspark.sql.functions import col
sc = SparkContext(conf=SparkConf())
spark = SparkSession.builder.master("local[*]").appName("FirstApp").getOrCreate()

Calculate

work.ipynb

  • 總體思路:通過設置鍵值對和利用RDD.sortByKey()方法對數據排序,取中位數

  • 打開文件,導入數據,利用str.split()分隔字符串

file = open("hdfs://master:9000/sparkdata/data1.txt")
dataStrList = file.read().split(',')
  • 將字符串轉換爲浮點類型
dataFloatList = []
for i in dataStrList:
    dataFloatList.append(float(i))
  • 創建RDD,生成鍵值對
  • 排序
  • 取出Mapped RDD鍵集合
data = sc.parallelize(dataFloatList)
dataMapped = data.map(lambda x: (x, x))
dataSorted = dataMapped.sortByKey(lambda x: x[0]).keys()
  • 統計元素數
  • 區分奇偶情況(可省略)
  • 計算中位數
N = dataSorted.count()
if N % 2 == 0:
    preHalfList = dataSorted.take(N / 2 + 1)
    avg = (preHalfList[-1] + preHalfList[-2]) / 2
else:
    avg = dataSorted.take(N / 2 + 1)[-1]
  • 得出結果
>>> avg
>>> -0.435513

Verification

work.ipynb

  • 總體思路:通過計算比得出的avg更大數字的個數cntM和更小得數字的個數cntN是否相等,判斷是否爲中位數

  • 初始化

cntM = 0
cntN = 0
  • 通過RDD.collect()RDD轉換爲list
dataSortedList = dataSorted.collect()
  • 統計比avg更大數字的個數cntM和更小得數字的個數cntN
for i in dataSortedList:
    if (i >= avg):
        cntM += 1
    else:
        cntN +=1
  • 輸出結果驗證
>>> cntM, cntN, cntM == cntN
>>> (5000, 5000, True)

Conclusion

  • 首先隨機生成10000個浮點數,存儲到data1.txt中;
  • 然後基於pyspark環境導入文件、分隔字符串並轉換爲浮點類型、構建RDD對象;
  • 再生成Map鍵值對,進行排序,取出中間兩個數字做平均值,作爲中位數
  • 最後統計原數組中比該“中位數”大/小的數字的個數,相等則驗證該“求中位數算法”正確。

The End

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章