如何根据pyspark数据框中的某些条件将列名称作为withColumn语句的一部分?

时间:2019-03-26 19:49:35

标签: python pyspark

我有一个带有伪编码值的pyspark数据帧,如下所示:

Checked out revision 0.

我想做的是创建一个“ vw_format”列,其中“ vw_format”的每一行都包含一个字符串,该字符串包含该行中不为0的列名。 所以我想要这样的一列:

    user    domain1      domain2     domain3..........  conversions

    abcd    1            0           0                   1
    gcxe    0            1           2                   0
    .       .            .           .                   .
    .       .            .           .                   .
    .       .            .           .                   .
    .       .            .           .                   .

我该怎么做?我无法使用collect(),因为我的数据集很大。

“ 1 |”和“ 0 |”只是代表我已经实现的转换列。

我尝试过这种方式,但是没有用:

    'vw_format'

    '1|d domain1'
    '0|d domain1 domain3'
         .
         .
         .

在使用iterrows()之前,我已经在python中完成了此操作,但是在pyspark中却不能。 注意:-这是一个大数据集。

1 个答案:

答案 0 :(得分:0)

您可以使用concat_wswhen完成此操作。

首先为“域”列创建一个列名列表。您必须对此进行调整以满足您的需求,但是根据您在问题中提供的内容,以下方法可能会起作用:

domains = [c for c in df.columns if c.lower().startswith("domain")]
print(domains)
#['domain1', 'domain2', 'domain3']

现在使用conversions作为分隔符将"d"列和文字字符串"|"连接起来。接下来,将此结果与domains中具有非零值且以空格作为分隔符的每一列连接。

我们利用以下事实:如果不满足条件且未指定when,则null默认返回otherwise。 (串联将跳过null。)

from pyspark.sql.functions import col, concat_ws, lit, when

df.withColumn(
    "vw_format", 
    concat_ws(
        " ", 
        concat_ws("|", "conversions", lit("d")), 
        *[when(col(c) != 0, lit(c)) for c in domains]
    )
).show(truncate=False)
#+----+-------+-------+-------+-----------+-------------------+
#|user|domain1|domain2|domain3|conversions|vw_format          |
#+----+-------+-------+-------+-----------+-------------------+
#|abcd|1      |0      |0      |1          |1|d domain1        |
#|gcxe|0      |1      |2      |0          |0|d domain2 domain3|
#+----+-------+-------+-------+-----------+-------------------+