Pyspark熔化空列

时间:2018-06-12 07:02:36

标签: python pyspark apache-spark-sql

我有一个如下所示的数据框:

# +----+------------+----------+-----------+
# | id |  c_type_1  | c_type_2 |  c_type_3 |
# +----+------------+----------+-----------+
# |  1 |    null    |   null   |     r     |
# |  2 |     a      |   null   |    null   |
# |  3 |    null    |   null   |    null   |
# +---+-------------+----------+-----------+

我需要把它转换成这样的东西:

# +----+------------+------------+
# | id |   c_type   | c_type_val |
# +----+------------+------------+
# |  1 |  c_type_3  |     r      |
# |  2 |  c_type_1  |     a      |
# |  3 |    null    |    null    |
# +---+-------------+------------+

每行只有一个c_type值,或者所有c_type值都为null。

我目前正在融化这些行:

def melt(df, id_cols, value_cols, c_type, c_value):
    v_arr = []
    for c in value_cols:
        v_arr.append(struct(lit(c).alias(c_type), col(c).alias(c_value)))

    vars_and_vals = array(*v_arr)

    tmp = df.withColumn("vars_and_vals", explode(vars_and_vals))

    cols = id_cols + [
        col("vars_and_vals")[x].alias(x) for x in [c_type, c_value]]
    return tmp.select(*cols)


melted = melt(df, df.columns[:1], df.columns[1:4], 'c_type', 'c_type_val')

melted.filter(melted.c_type_val.isNotNull()).show()

问题是过滤c_type_val的空值会过滤掉id == 3的行(任何具有null c_type的行)。我需要一种方法来融化和过滤以将第三行保留为null c_type和value。

1 个答案:

答案 0 :(得分:0)

我尝试使用pandas,它可能会给你一个解决这个问题的想法,

temp=df.filter(like='c_type')
df= pd.merge(df,temp[temp.notnull()].stack().reset_index(), left_index=True, right_on=['level_0'],how='left')
df=df[['id','level_1',0]].reset_index(drop=True).rename(columns={'level_1':'c_type',0:'c_type_val'})
print df

输出:

   id    c_type c_type_val
0   1  c_type_3          r
1   2  c_type_1          a
2   3       NaN        NaN