標籤:
PySpark處理資料並圖表分析
PySpark簡介
- 官方對PySpark的釋義為:“PySpark is the Python API for Spark”。 也就是說pyspark為Spark提供的Python編程介面。
- Spark使用py4j來實現python與java的互操作,從而實現使用python編寫Spark程式。Spark也同樣提供了pyspark,一個Spark的python shell,可以以互動方式使用Python編寫Spark程式。 如:
from pyspark import SparkContext sc = SparkContext("local","Job Name", pyFiles=['MyFile.py', 'lib.zip', 'app.egg']) words =sc.textFile("/usr/share/dict/words") words.filter(lambda w:w.startswith("spar")).take(5)
PySpark文檔首頁介面:
PySpark是構建在Java API之上的,如:
處理資料並圖表分析
下面我通過PySpark對真實的資料集進行處理,並作圖形來分析。首先我需要介紹下資料集以及資料處理的環境。
資料集
MovieLens資料集是由Minnesota大學的GroupLens Research Project對電影評分網站(movielens.umn.edu)收集的,資料集包含了1997年9月19日到1998年四月22日間共七個月的資料。這些資料已經被處理過了(清除了那些評分次數少於20次以及資訊沒有填寫完整的資料)
MovieLens資料集:
MovieLens資料集,使用者對自己看過的電影進行評分,分值為1~5。MovieLens包括兩個不同大小的庫,適用於不同規模的演算法.小規模的庫是943個獨立使用者對1682部電影作的10000次評分的資料(我是用這個小規模作資料處理和分析);通過對資料集分析,為使用者預測他對其他未觀看的電影的打分,將預測分值高的電影推薦給使用者,認為這些電影是使用者下一步感興趣的電影。
資料集結構:
1、943個使用者對1682場電影評分,評判次數為100000次,評分標準:1~5分。
2、每位使用者至少評判20場電影。
3、簡單地統計了使用者的一些資訊 (age, gender, occupation, zip)
資料用途:
供科研單位和研發企業使用,可用於資料採礦、推薦系統,人工智慧等領域,複雜網路研究等領域。
資料處理的環境
- Hadoop偽分布環境
- Spark Standalone環境
- Anaconda環境:(:https://www.continuum.io/downloads)
- Anaconda Python 是 Python 科學技術包的合集,包含超過400個流行的科學計算、數學、工程以及資料分析用的包。這裡我主要是用它的一些包,免得自己裝一些Python包麻煩。
其他:
處理一(使用者年齡統計分析)
處理一簡介:
通過對使用者資料處理,獲得使用者資訊中的年齡。然後對年齡進行統計並使用Python中的圖形架構Matplotlib產生柱狀圖,最後通過柱狀圖分析觀看電影的觀眾年齡分布趨勢。
處理一所有代碼:
#載入HDFS上面的使用者資料user_data = sc.textFile("hdfs:/input/ml-100k/u.user")#列印載入的使用者資訊第一條user_data.first()#用"|"分割符分割每一行的資料,然後將資料返回到user_fieldsuser_fields = user_data.map(lambda line: line.split("|"))#統計總的使用者數num_users = user_fields.map(lambda fields: fields[0]).count()#統計性別的種類數,distinct()函數用來去重。num_genders = user_fields.map(lambda fields:fields[2]).distinct().count()#統計職位種類數num_occupations = user_fields.map(lambda fields:fields[3]).distinct().count()#統計郵遞區號種類數num_zipcodes = user_fields.map(lambda fields:fields[4]).distinct().count()#列印統計的這些資訊print "Users: %d, genders: %d, occupations: %d, ZIP codes: %d" % (num_users, num_genders, num_occupations, num_zipcodes)#統計使用者年齡ages = user_fields.map(lambda x: int(x[1])).collect()#通過python中的matplotlib組建圖表提供給分析師分析import matplotlib.pyplot as plthist(ages, bins=20, color='lightblue', normed=True)fig = plt.gcf()fig.set_size_inches(16, 10)plt.show()
進入Spark安裝目錄的,然後輸入如下命令開啟pyspark:
./bin/pyspark
之後載入HDFS上面的使用者資料(u.user),然後通過user_data.first()列印第一條資料顯示資料格式。
統計的HDFS上面的所有使用者資訊:總共943位使用者、男女兩種性別、21中職位、795個不同的郵遞區號。
Matplotlib是一個Python的圖形架構,下面為matplotlib工作過程的列印資訊:
Matplotlib對統計後的資料圖形化顯示:
使用者年齡分布圖:
結論:
通過產生的柱狀圖我們可以看出這些電影觀眾年齡段趨於青年,並且大部分使用者年齡都在15到35之間。
處理二(使用者職位統計分析)
處理二簡介:
首先對使用者資料處理,獲得使用者資訊中的職位種類以及每種職位使用者個數。然後對職位進行統計並使用Python中的圖形架構Matplotlib產生柱狀圖,最後通過柱狀圖分析觀看電影的觀眾職位以及人數分布趨勢。
處理二所有代碼:
#處理職位那一列,通過類似於MapReduce經典例子WordCount處理過程處理職位count_by_occupation = user_fields.map(lambda fields: (fields[3], 1)).reduceByKey(lambda x, y: x + y).collect()#匯入numpy模組import numpy as np#擷取使用者職位,並作為柱狀圖的x軸資料顯示x_axis1 = np.array([c[0] for c in count_by_occupation])#擷取使用者的各個職位元,並作為y軸資料顯示y_axis1 = np.array([c[1] for c in count_by_occupation])#讓x軸類別的顯示按照y軸中每種職位的個數升序排序x_axis = x_axis1[np.argsort(y_axis1)]#y軸也是升序y_axis = y_axis1[np.argsort(y_axis1)]#設定柱狀圖中x軸範圍以及widthpos = np.arange(len(x_axis))width = 1.0#將統計的職位資訊使用matplotlib產生柱狀圖from matplotlib import pyplot as pltax = plt.axes()ax.set_xticks(pos + (width / 2))ax.set_xticklabels(x_axis)plt.bar(pos, y_axis, width, color='lightblue')plt.xticks(rotation=30)fig = plt.gcf()fig.set_size_inches(16, 10)plt.show()
使用者職位資訊處理過程:
使用者職位資訊統計並產生柱狀圖:
使用者職位分布圖:
結論:
從最終產生的圖表中,我們可以看齣電影觀眾大部分都是student, educator, administrator, engineer和programmer。並且student的人數領先其他職位一大截。
處理三(電影發布資訊統計分析)
處理三簡介:
- 首先對使用者資料處理,獲得使用者評價的電影發布時間資訊。然後以1998年為最高年限減去電影發布的年限(資料集統計的時間為1998年)得到的值作為x軸,接著通過Python中的圖形架構Matplotlib產生柱狀圖,最後通過柱狀圖分析當時電影發布時間趨勢。
- 電影資訊有一些髒資料,所以需要先作處理。
處理三所有代碼:
#從HDFS中載入u.item資料movie_data = sc.textFile("hdfs:/input/ml-100k/u.item")#列印第一條資料,查看資料格式print movie_data.first()#統計電影總數num_movies = movie_data.count()print "Movies: %d" % num_movies#定義函數功能為對電影資料預先處理,對於錯誤的年限,使用1900填補def convert_year(x): try: return int(x[-4:]) except: return 1900 # there is a 'bad' data point with a blank year,which we set to 900 and will filter out later#使用"|"分隔字元分割每行資料movie_fields = movie_data.map(lambda lines: lines.split("|"))#提取分割後電影發布年限資訊,並做髒資料預先處理years = movie_fields.map(lambda fields: fields[2]).map(lambda x:convert_year(x))#擷取那些年限為1900的電影(部分為髒資料)years_filtered = years.filter(lambda x: x != 1900)#計算齣電影發布時間與1998年的年限差movie_ages = years_filtered.map(lambda yr: 1998-yr).countByValue()#將年限差作為x軸,電影數量作為y軸作柱狀圖values = movie_ages.values()bins = movie_ages.keys()from matplotlib import pyplot as plt1plt1.hist(values, bins=bins, color='lightblue', normed=True)fig = plt1.gcf()fig.set_size_inches(16,10)plt1.show()
從HDFS上載入電影資料並列印第一條資料查看資料格式:
列印的電影資料格式:
列印的電影總數:
電影發布年限統計並產生柱狀圖:
電影發布年限分布圖:(x軸為1998減去電影發布年限)
結論:
從最終產生的圖表中,我們可以看出絕大多數電影發布時間都在1988-1998年之間。
處理四(使用者評分統計分析)
處理四簡介:
首先對使用者資料處理,獲得使用者對電影的評分數,然後統計評分1-5的每個評分個數,然後繪製圖表供分析。
處理四所有代碼:
#從HDFS上面載入使用者評分資料rating_data = sc.textFile("hdfs:/input/ml-100k/u.data")print rating_data.first()#統計評分記錄總數num_ratings = rating_data.count()print "Ratings: %d" % num_ratings#使用"\t"符分割每行資料rating_data = rating_data.map(lambda line: line.split("\t"))#擷取每條資料中的使用者評分數集合ratings = rating_data.map(lambda fields: int(fields[2]))#擷取最大評分數max_rating = ratings.reduce(lambda x, y: max(x, y))#擷取最小評分數min_rating = ratings.reduce(lambda x, y: min(x, y))#擷取平均評分數mean_rating = ratings.reduce(lambda x, y: x + y) / num_ratings#擷取評分中位元median_rating = np.median(ratings.collect())#每位使用者平均評分ratings_per_user = num_ratings / num_users#每位使用者評了幾場電影ratings_per_movie = num_ratings / num_movies#列印上面這些資訊print "Min rating: %d" % min_ratingprint "Max rating: %d" % max_ratingprint "Average rating: %2.2f" % mean_ratingprint "Median rating: %d" % median_ratingprint "Average # of ratings per user: %2.2f" % ratings_per_userprint "Average # of ratings per movie: %2.2f" % ratings_per_movie#擷取評分資料count_by_rating = ratings.countByValue()import numpy as np#x軸的顯示每個評分(1-5)x_axis = np.array(count_by_rating.keys())#y軸顯示每個評分所佔機率,總機率和為1y_axis = np.array([float(c) for c in count_by_rating.values()])y_axis_normed = y_axis / y_axis.sum()pos = np.arange(len(x_axis))width = 1.0#使用matplotlib產生柱狀圖from matplotlib import pyplot as plt2ax = plt2.axes()ax.set_xticks(pos + (width / 2))ax.set_xticklabels(x_axis)plt2.bar(pos, y_axis_normed, width, color='lightblue')plt2.xticks(rotation=30)fig = plt2.gcf()fig.set_size_inches(16, 10)plt2.show()
從HDFS載入資料
評分記錄總數:
評分的一些統計資訊;
統計評分資訊並產生柱狀圖:
使用者電影評價分布圖:
結論:
我們可以看齣電影的評分大都在3-5分之間。
處理五(使用者總評分統計分析)
處理五簡介:
首先對使用者資料處理,獲得使用者對電影的總評分數(每位至少評價20次,評分在1-5之間)然後繪製圖表供分析。
處理四所有代碼:
#擷取使用者評分次數和每次評分user_ratings_grouped = rating_data.map(lambda fields: (int(fields[0]),int(fields[2]))).groupByKey()#使用者ID以及該使用者評分總數user_ratings_byuser = user_ratings_grouped.map(lambda (k, v): (k,len(v)))#列印5條結果user_ratings_byuser.take(5)#產生柱狀圖from matplotlib import pyplot as plt3user_ratings_byuser_local = user_ratings_byuser.map(lambda (k, v):v).collect()plt3.hist(user_ratings_byuser_local, bins=200, color='lightblue',normed=True)fig = plt3.gcf()fig.set_size_inches(16,10)plt3.show()
列印使用者5條處理後的結果:
產生每位使用者評分總數分布圖:
結論:
可以看出總評分在100以內的佔了絕大多數。當然,100到300之間還是有一部分的。
注意事項
1、要顯示Python表徵圖,必須要作業系統有圖形介面。
2、Python必要有matplotlib 模組。
3、必須要以root使用者開啟PySpark,不然會報以下錯誤,沒有許可權串連x Server。
PySpark處理資料並圖表分析