pyspark行转列、列转行或宽表转窄表、窄表转宽表

列转行(宽表转窄表)

1
2
3
4
5
6
7
8
9
10
11
12
from pyspark.sql import functions as F


def unpivot(df, keys):
    # 参数说明 df  dataframe   keys 待转换表中需要保留的主键key,以list[]类型传入
    # 转换是为了避免字段类不匹配,统一将数据转换为string类型,如果保证数据类型完全一致,可以省略该句
    df = df.select(*[F.col(_).astype("string") for _ in df.columns])
    cols = [_ for _ in df.columns if _ not in keys]
    stack_str = ','.join(map(lambda x: "'%s', %s" % (x, x), cols))
    # feature, value 转换后的列名,可自定义
    df = df.selectExpr(*keys, "stack(%s, %s) as (feature, value)" % (len(cols), stack_str))
    return df

代码演示

行转列(窄表转宽表)

1
2
3
4
5
6
7
8
from pyspark.sql import functions as F


def pivot(df, keys, column, column_value, column_value_list):
    # 参数说明 df  dataframe   keys 待转换表中需要保留的主键key,以list[]类型传入
    # column 待转换的列名  column_value column对应值的列名  column_value_list column内需要成列值,也是新生成表的列名
    # .fillna(-999.0)  行转列时有时对应的列没有值,就会产生null值,fillna会对null做处理,转换为其他值,如不需要可以删除
    return df.groupBy(keys).pivot(column, column_value_list).agg(F.first(column_value, ignorenulls=True)).fillna(-999.0)

代码演示