目錄
pyspark連接mysql
前提是需要下載jar包。
Mysql-connector-java.jar
from pyspark import SparkContext
from pyspark.sql import SQLContext
import pyspark.sql.functions as F
sc = SparkContext("local", appName="mysqltest")
sqlContext = SQLContext(sc)
df = sqlContext.read.format("jdbc").options(
url="jdbc:mysql://localhost:3306/mydata?user=root&password=mysql&"
"useUnicode=true&characterEncoding=utf-8&useJDBCCompliantTimezoneShift=true&"
"useLegacyDatetimeCode=false&serverTimezone=UTC ", dbtable="detail_data").load()
df.show(n=5)
sc.stop()
pyspark SQL常用語法
pyspark SQL的部分語法和pandas的很相似。
輸出schema
df.printSchema()
# root
# |-- id: integer (nullable = true)
# |-- 省份: string (nullable = true)
預覽表
df.show(n=5)
# +----+------+------+------+------+
# | id| 省份| 城市| 區縣| 區域|
# +----+------+------+------+------
# |2557|廣東省|深圳市|羅湖區|春風路
# ...
統計數量
print(df.count())
# 47104
輸出列名稱和字段類型
print(df.columns)
# ['id', '省份', '城市', '區縣', '區域', '小區', '源地址',...
print(df.dtypes)
# [('id', 'int'), ('省份', 'string'), ('城市', 'string'),...
選擇列
df.select('城市', '區縣', '區域', '小區').show()
# +------+------+------+--------------+
# | 城市| 區縣| 區域| 小區|
# +------+------+------+--------------+
# |深圳市|羅湖區|春風路| 凱悅華庭|
# |深圳市|羅湖區|春風路| 置地逸軒|
# ...
爲選擇的列賦予新名稱
可以看到有兩種方式來對指定列做操作:
- 列名稱是英文的話,直接在df後面用點號調用
- 列名稱非英文,可以在後面用中括號調用
df.select(df.id.alias('id_value'), '小區').show()
# +--------+--------------+
# |id_value| 小區|
# +--------+--------------+
# | 2557| 凱悅華庭|
# | 2558| 置地逸軒|
# ...
df.select(df["城市"].alias('city'), '小區').show()
# +------+--------------+
# | city| 小區|
# +------+--------------+
# |深圳市| 凱悅華庭|
# |深圳市| 置地逸軒|
# ...
按條件過濾
在filter中定義過濾條件,如果要進行多條件過濾,使用以下符號:
& 代表 and
| 代表or
~ 代表not
df.select('城市', '區縣', '區域', '小區').filter(df["小區"] == '凱悅華庭').show()
# +------+------+------+--------+
# | 城市| 區縣| 區域| 小區|
# +------+------+------+--------+
# |深圳市|羅湖區|春風路|凱悅華庭|
# ...
df.select('城市', '區縣', '區域', '小區').filter((df["城市"] == '深圳市') & (df["區縣"] == '南山區')).show()
# +------+------+------+----------------+
# | 城市| 區縣| 區域| 小區|
# +------+------+------+----------------+
# |深圳市|南山區|白石洲|中海深圳灣畔花園|
# |深圳市|南山區|白石洲| 僑城豪苑二期|
# ...
# 可以直接在filter裏面寫條件表達式
df.select('id', '城市', '區縣', '區域', '小區').filter("id = 5000").show()
構造新列
使用以下兩種方式構造新列,其中使pyspark.sql.functions
下提供很多sql操作函數。
我們使用functions
下的lit
構造新列。
import pyspark.sql.functions as F
df.select(df["城市"] + 1, '城市', '小區').show()
# +----------+------+--------------+
# |(城市 + 1)| 城市| 小區|
# +----------+------+--------------+
# | null|深圳市| 凱悅華庭|
df.select(F.lit("test").alias('城市plus'), '城市', '小區').show()
# +--------+------+--------------+
# |城市plus| 城市| 小區|
# +--------+------+--------------+
# | test|深圳市| 凱悅華庭|
增加行
# 取出一行
df2 = df.limit(1) # one row
# 增加行
print(df.count()) # 47104
print(df.unionAll(df2).count()) # 47105
刪除重複記錄
我們上面增加了一個重複行,目前條數是47105,我們接下來看去除重複行之後47104。
另外一個問題,對於原始數據來說,我們的id是不重複的,但是其他字段可能會重複。
因此我們去重的時候應該去掉id的影響,這裏可以使用下面第二種指定字段去重。
# 刪除重複記錄
print(df.drop_duplicates().count()) # 47104
print(df.drop_duplicates(['省份', '城市', '區縣', '區域', '小區']).count())
刪除列
# 刪除列
print(df.drop('id').columns)
# ['省份', '城市', '區縣', '區域', '小區', '源地址',...
刪除缺失值行
# 刪除存在缺失的記錄
print(df.dropna().count()) # 47092
# 刪除指定字段中存在缺失的記錄
print(df.dropna(subset=['省份', '城市']).count()) # 47104
填充缺失值
填充缺失值,指定字段需要填充的值。
print(df.fillna({'省份': "廣東省", '城市': '深圳市'}))
分組統計和計算
# 分組統計
df_g1 = df.groupby("區縣").count()
df_g1.show()
# +--------+-----+
# | 區縣|count|
# +--------+-----+
# | 龍華區| 4217|
# ...
# 分組計算
df.groupby('區縣').agg(F.max(df['總價'])).show()
+--------+----------+
# | 區縣| max(總價)|
# +--------+----------+
# | 龍華區|5200.00000|
# | 福田區|8300.00000|
# | 羅湖區|7000.00000|
# | 坪山區|1588.00000|
# | 南山區|9800.00000|
# | 龍崗區|4000.00000|
# | 鹽田區|5500.00000|
# | 光明區|5200.00000|
# |大鵬新區|3500.00000|
# | 寶安區|8800.00000|
# +--------+----------+
函數計算
同樣,函數計算由pyspark.sql.functions
提供。
# 函數計算
df.select(F.max(df["總價"])).show() # 最大值
# +----------+
# | max(總價)|
# +----------+
# |9800.00000|
# +----------+
df.select(F.min(df["總價"])).show() # 最小值
# +---------+
# |min(總價)|
# +---------+
# | 1.10000|
# +---------+
df.select(F.avg(df["總價"])).show() # 平均值
# +-------------+
# | avg(總價)|
# +-------------+
# |577.736916000|
# +-------------+
df.select(F.countDistinct(df["總價"])).show() # 去重後再統計
# |count(DISTINCT 總價)|
# +--------------------+
# | 1219|
# +--------------------+
df.select(F.count(df["總價"])).show() # 去掉缺失值會再統計
# +-----------+
# |count(總價)|
# +-----------+
# | 47104|
# +-----------+
其餘的函數:
# 'lit': 'Creates a :class:`Column` of literal value.',
# 'col': 'Returns a :class:`Column` based on the given column name.',
# 'column': 'Returns a :class:`Column` based on the given column name.',
# 'asc': 'Returns a sort expression based on the ascending order of the given column name.',
# 'desc': 'Returns a sort expression based on the descending order of the given column name.',
#
# 'upper': 'Converts a string expression to upper case.',
# 'lower': 'Converts a string expression to upper case.',
# 'sqrt': 'Computes the square root of the specified float value.',
# 'abs': 'Computes the absolutle value.',
#
# 'max': 'Aggregate function: returns the maximum value of the expression in a group.',
# 'min': 'Aggregate function: returns the minimum value of the expression in a group.',
# 'first': 'Aggregate function: returns the first value in a group.',
# 'last': 'Aggregate function: returns the last value in a group.',
# 'count': 'Aggregate function: returns the number of items in a group.',
# 'sum': 'Aggregate function: returns the sum of all values in the expression.',
# 'avg': 'Aggregate function: returns the average of the values in a group.',
# 'mean': 'Aggregate function: returns the average of the values in a group.',
# 'sumDistinct': 'Aggregate function: returns the sum of distinct values in the expression.',
描述性分析
df.describe("總價").show()
# +-------+-----------------+
# |summary| 總價|
# +-------+-----------------+
# | count| 47104|
# | mean| 577.736916000|
# | stddev|544.7605196104298|
# | min| 1.10000|
# | max| 9800.00000|
# +-------+-----------------+
最後,記得stop一下。
sc.stop()
參考鏈接
Quick Start
Spark Python API (Sphinx)
PySpark SQL常用語法
spark官方文檔 翻譯 之pyspark.sql.SQLContext