文章目录
pyspark中的dataframe的官方定义为:分布式数据集合,其等效于Spark SQL中的关系表,可以使用SparkSession中的各种函数来创建。pyspark.sql.DataFrame和Pandas.DataFrame二者有相似之处,后续会对二者进行比较。
agg()、alias()
agg()表示在没有分组的情况下对整个dataframe进行聚合(还有另一种分组的聚合:df.groupBy.agg()),alias()相当于取了别名。
import pandas as pd
import numpy as np
from pyspark.sql import functions as fn
from pyspark.sql import SparkSession
spark=SparkSession.builder.appName("local").enableHiveSupport().getOrCreate()
pdf=pd.DataFrame(np.arange(20).reshape(4,5),columns=["a","b","c","d","e"])
df=spark.createDataFrame(pdf)
df.agg(fn.count("a").alias("a_count"),fn.countDistinct(df.b),fn.sum("c"),fn.max("d").alias("max"),fn.min("e")).show()
+-------+-----------------+------+---+------+
|a_count|count(DISTINCT b)|sum(c)|max|min(e)|
+-------+-----------------+------+---+------+
| 4| 4| 38| 18| 4|
+-------+-----------------+------+---+------+
colRegex()
以正则表达式选择dataframe的列名
df = spark.createDataFrame([("a", 1), ("b", 2), ("c", 3)], ["Col1", "Col2"])
df.select(df.colRegex("`(col)\d`")).show()
+----+----+
|Col1|Col2|
+----+----+
| a| 1|
| b| 2|
| c| 3|
+----+----+
createGlobalTempView()
使用此DataFrame创建全局临时视图。此临时视图的生命周期与此Spark应用程序相关联。 如果目录中已存在视图名称,则抛出TempTableAlreadyExistsException。
>>> df.createGlobalTempView("people")
>>> df2 = spark.sql("select * from global_temp.people")
>>> sorted(df.collect()) == sorted(df2.collect())
True
>>> df.createGlobalTempView("people")
AnalysisException: u"Temporary table 'people' already exists;"
与此类似的还有createOrReplaceGlobalTempView(),该方法创建同名视图不会程序异常,新的会直接替换旧的。此外,还有createOrReplaceTempView()、createTempView()方法,这两个方法与前面两个方法的区别在于:前者是全局的,后者是本地的。
drop()
返回删除指定列的新DataFrame。 如果原DataFrame不包含给定的列名,则这是一个无操作。
>>> df.drop('age').collect()
[Row(name='Alice'), Row(name='Bob')]
>>> df.join(df2, df.name == df2.name, 'inner').drop(df.name).collect()
[Row(age=5, height=85, name='Bob')]
exceptAll(other)
两个dataframe做差集
>>> df1 = spark.createDataFrame([("a", 1), ("a", 1), ("a", 1), ("a", 2), ("b", 3), ("c", 4)], ["C1", "C2"])
>>> df2 = spark.createDataFrame([("a", 1), ("b", 3)], ["C1", "C2"])
>>> df1.exceptAll(df2).show()
+---+---+
| C1| C2|
+---+---+
| a| 1|
| a| 1|
| a| 2|
| c| 4|
+---+---+
filter()、where()
filter()和where()函数二者功能是相同的,条件过滤。
>>> df.filter(df.age > 3).collect()
[Row(age=5, name='Bob')]
>>> df.where(df.age == 2).collect()
[Row(age=2, name='Alice')]
groupBy()
比较简单,类似于sql中的分组,后面常跟聚合函数agg()
>>> sorted(df.groupBy('name').agg({'age': 'mean'}).collect())
[Row(name='Alice', avg(age)=2.0), Row(name='Bob', avg(age)=5.0)]
>>> sorted(df.groupBy(['name', df.age]).count().collect())
[Row(name='Alice', age=2, count=1), Row(name='Bob', age=5, count=1)]
intersectAll(other)
求两个dataframe的交集
df1 = spark.createDataFrame([(“a”, 1), (“a”, 1), (“b”, 3), (“c”, 4)],[“C1”, “C2”])
df2 = spark.createDataFrame([(“a”, 1), (“a”, 1), (“b”, 3)], [“C1”, “C2”])
df1.intersectAll(df2).sort("C1", "C2").show()
+---+---+
| C1| C2|
+---+---+
| a| 1|
| a| 1|
| b| 3|
+---+---+
join(other, on=None, how=None)
两个datafram链接操作
>>> cond = [df.name == df3.name, df.age == df3.age]
>>> df.join(df3, cond, 'outer').select(df.name, df3.age).collect()
[Row(name='Alice', age=2), Row(name='Bob', age=5)]
>>> df.join(df4, ['name', 'age']).select(df.name, df.age).collect()
[Row(name='Bob', age=5)]
sort()、orderby()
排序操作
>>> df.sort("age", ascending=False).collect()
[Row(age=5, name='Bob'), Row(age=2, name='Alice')]
>>> df.orderBy(["age", "name"], ascending=[0, 1]).collect()
[Row(age=5, name='Bob'), Row(age=2, name='Alice')]
replace(to_replace, value=, subset=None)
将指定值替换为另一个值
- to_replace表示要被替换掉的值,可以是bool, int, long, float, string, list or dict,如果是dic,则参数value将被忽略。
- value表示将要替换的值,可以是bool, int, long, float, string, list or None. 如果value是列表,则value应与to_replace具有相同的长度和类型。 如果value是标量且to_replace是序列,则value用作to_replace中每个项的替换。
- subset表示需要的替换的列的范围。
df4.replace('Alice', None).show()
#或者
df4.replace({'Alice': None}).show()
+----+------+----+
| age|height|name|
+----+------+----+
| 10| 80|null|
| 5| null| Bob|
|null| null| Tom|
|null| null|null|
+----+------+----+
df4.replace(['Alice', 'Bob'], ['A', 'B'], 'name').show()
+----+------+----+
| age|height|name|
+----+------+----+
| 10| 80| A|
| 5| null| B|
|null| null| Tom|
|null| null|null|
+----+------+----+
withColumn()
通过添加列或替换具有相同名称的现有列来构造新的DataFrame。列表达式必须是此DataFrame上的表达式; 如果尝试从其他数据框添加列将引发错误。
- 运用withcolumn()通过现有列,构造新的列
>>> df.withColumn('age2', df.age + 2).collect()
[Row(age=2, name='Alice', age2=4), Row(age=5, name='Bob', age2=7)]
- 运用withcolumn()修改列字段类型
df=df.withColumn("price",df.price.astype("float"))
# 或者
df=df.withColumn("price",df["price"].cast(FloatType())
- 运用withcolumn()和自定义函数修改某列或增加新列,其中,update_units是我的自定义函数,关于自定义函数这块后面会专门来讲的,这里暂时先用着。
from pyspark.sql import functions
update_units_udf=functions.udf(update_units,StringType())
df=df.withColumn("quant_first",update_units_udf("quant_first"))
df=df.withColumn("unit_price",df.price/(df.quant_first_int*df.quant_second_int))
withColumnRenamed(existing, new)
修改列名
>>> df.withColumnRenamed('age', 'age2').collect()
[Row(age2=2, name='Alice'), Row(age2=5, name='Bob')]
到这里为止,pyspark.sql.DataFrame的基本常用API就讲完了,当还有一些像show()、describe()、select()等等之类没讲,简单的很,没啥可讲的,基本用法讲完后,后面会陆续更新一些高阶用法。