select()就是列名进行选择,collect()就是对数据的最终结果或者中间结果进行收集,非常类似于Java的Stream流的collect(),对RDD跟DataFrame的进行校验,应该避免在大的数据集中使用collect()防止内存被爆掉。
这里的案例除非是特别创建,否则都是pyspark(一)的数据
filter就是对一个dataframe进行筛选,这里一般是列筛选,某一个列大于或者小于,包含或者startswith等等根据列的值进行筛选
from pyspark.sql import SparkSession
import pandas as pd
import pyspark.sql.functions as F
import pyspark.sql.types as T
# 创建spark与dataframe
spark=SparkSession.builder.appName("alpha").getOrCreate()
df=spark.read.csv(china_order_province_path,header=True)
df=spark.createDataFrame(data=[[],[]],shema=column_name)
#dataframe.filter(condition)这里进行筛选,很类似于pandas里的DataFrame(df["col_name"]><=等等) isin startswith,contains,like等等,这边进行筛选的方式其实有很多,自己看着用。
df_filtered=df.filter(df["col_name"]>|< |== |contains()| in col_lists)
pandas 对某一列进行处理,这个跟pandas里的df.apply(lambda x:x[“col_name”]+“end”,axis=1)
df=df.withColumn("new_col_name",df["col_name"].cast(T.StringType()))
#一个常用的案例
spark = SparkSession.builder.appName("beta").getOrCreate()
df=spark.read.csv(china_order_province_path,header=True)
@udf
def exchange_city_level(input_string):
if "三" in input_string:
return "3"
elif "二" in input_string:
return "2"
elif "一" in input_string:
return "1"
else:
return "18"
df = df.withColumn("city_level", exchange_city_level(df['城市等级']))
**有时间测试一下直接使用匿名函数lambda来进行,对一些很小的数据处理能很快速解决,也比较好看,这样的方式太过于复杂。**
一个小tips,不知道是spark环境的问题,还是版本问题,在处理很小数据过程中,spark表现的非常的卡顿,处理后的dataFrame.toPandas()有时候也不是很好用,所以可以直接使用collect().__len__()来快速看结果是否,而也不需要show(10)等等
这个跟pandas是一致的去除某一列drop(col_name_list),dropDuplicates(col_name_list),distinct()
data = [("James", "Sales", 3000),
("Michael", "Sales", 4600),
("Robert", "Sales", 4100),
("Maria", "Finance", 3000),
("James", "Sales", 3000),
("Scott", "Finance", 3300),
("Jen", "Finance", 3900),
("Jeff", "Marketing", 3000),
("Kumar", "Marketing", 2000),
("Saif", "Sales", 4100),
("Saif", "Sales", 4200),
]
data_columns = ["employee_name", "department", "salary"]
df_beta = spark.createDataFrame(data=data, schema=data_columns)
df_beta.collect().__len__()
df_beta = df_beta.distinct()
df_test = df_beta.dropDuplicates(subset=['employee_name', "department"])
df_test.collect().__len__()
其实这么一大段就一个意思,distinct()是要所有行的数据都要一样才去除,dropDuplicates(subset=["col_a","col_b"]),col_a,与col_b的列一样就可以去除。也或者可以直接drop(col_name_list)
def spark_group_by():
"""
group_by跟pandas里的几乎一样,group_by其实就是统计基准列(可以catalog),然后统计数据列(value)的max,min,avg,sum,
:return:
"""
import pyspark.sql.functions as func
spark = SparkSession.builder.appName("alpha").getOrCreate()
df = spark.read.csv(path=r"D:\***\china_order_province.csv"
, header=True, encoding='utf-8')
df_grouped = df.groupBy(['省']).agg(func.avg("包邮率").alias("平均包邮率"),
func.sum("订单数").alias("总共订单数"),
func.max("常住人口2010").alias("省内最大城市人口"),
func.max("订单数").alias("最大订单数"))
temp_df = df_grouped.toPandas()
return df, df_grouped
这里相对于pandas好像多了一个semi的办法,这里其实就是a表在b表中存在的进行筛选,并不进行多表合并。
spark = SparkSession.builder.appName("test").getOrCreate()
emp = [(data)]
empColumns = [col_name_list]
dept = [data]
deptColumns=[col_name_list]
result = empDF.join(deptDF, empDF['emp_dept_id'] == deptDF["dept_id"], how="left_semi")
可能是因为我spark的版本的缘故,我没有办法直接使用这个,但是可以通过一个function_list(),然后使用一个for循环来进行遍历。
import pandas as pd
from pyspark.sql import SparkSession
import pyspark.sql.functions as F
import pyspark.sql.types as T
def upper_columns(df):
@F.udf(returnType=T.StringType())
def upper_low_case(string):
return string.upper()
"""给random columns 转换大小写"""
df = df.withColumn("new_random", upper_low_case(df['random']))
return df
def mail_free_ratio(df):
"""给包邮率进行一个简单的分级"""
@F.udf(returnType=T.StringType())
def level_three(val):
try:
value = float(val)
except ValueError as e:
value = 0
if value >= 0.95:
return "high"
elif (value >= 0.85) & (value < 0.95):
return "middle"
elif (value < 0.85) & (value >= 0):
return "low"
else:
return "none"
df = df.withColumn("mail_level", level_three(df['包邮率']))
return df
def exchange_level(df):
@F.udf(returnType=T.StringType())
def exchange_value(input_string):
if "三" in input_string:
return "3"
elif "二" in input_string:
return "2"
elif "一" in input_string:
return "1"
else:
return "18"
df = df.withColumn("city_level", exchange_value(df['城市等级']))
return df
def dataframe_alpha():
"""本来打算使用spark里的transform这个东西,有点像stream流的东西
结果2.4.5这个版本不支持,抽空把版本升级一下,
其实也可以通过一个function的list来对dataframe进行遍历,使用__call__()来依此调用,其实有点像stream流的意思了,
有趣的python"""
spark = SparkSession.builder.appName("alpha").getOrCreate()
df = spark.read.csv(r'D:\***\china_order_province_beta.csv',
header=True, encoding="utf-8")
# df.withColumn
func_list = [exchange_level, mail_free_ratio, upper_columns]
for ele in func_list:
df = ele.__call__(df)
df.show()
在对一个col或者几个col进行计算,结果不保存为dataFrame形式的时候,可以尝试将dataFrame转换为rdd然后来进行处理。
data = {
"col_a": ['abc_alpha', 'kmn_beta', 'xyz_gamma'],
"col_b": ['abc_delta', 'kmn_epsilon', 'xyz_zeta']
}
pandas_df = pd.DataFrame(data)
spark = SparkSession.builder.appName("test_beta").getOrCreate()
df = spark.createDataFrame(data=pandas_df)
rdd = df.rdd.flatMap(lambda x: x['col_a'].split("_")).collect()
rdd_beta = df.rdd.map(lambda x: x['col_b'].split("_")).collect()