将转换应用于多个列pyspark dataframe

问题描述 投票:2回答:1

假设我有以下spark-dataframe:

+-----+-------+
| word|  label|
+-----+-------+
|  red|  color|
|  red|  color|
| blue|  color|
| blue|feeling|
|happy|feeling|
+-----+-------+

可以使用以下代码创建:

sample_df = spark.createDataFrame([
        ('red', 'color'),
        ('red', 'color'),
        ('blue', 'color'),
        ('blue', 'feeling'),
        ('happy', 'feeling')
    ],
    ('word', 'label')
)

我可以执行groupBy()来获取每个单词标签对的计数:

sample_df = sample_df.groupBy('word', 'label').count()
#+-----+-------+-----+
#| word|  label|count|
#+-----+-------+-----+
#| blue|  color|    1|
#| blue|feeling|    1|
#|  red|  color|    2|
#|happy|feeling|    1|
#+-----+-------+-----+

然后pivot()sum()将标签计为列:

import pyspark.sql.functions as f
sample_df = sample_df.groupBy('word').pivot('label').agg(f.sum('count')).na.fill(0)
#+-----+-----+-------+
#| word|color|feeling|
#+-----+-----+-------+
#|  red|    2|      0|
#|happy|    0|      1|
#| blue|    1|      1|
#+-----+-----+-------+

转换此dataframe的最佳方法是将每行除以该行的总数?

# Desired output
+-----+-----+-------+
| word|color|feeling|
+-----+-----+-------+
|  red|  1.0|    0.0|
|happy|  0.0|    1.0|
| blue|  0.5|    0.5|
+-----+-----+-------+

实现此结果的一种方法是使用__builtin__.sum(NOT pyspark.sql.functions.sum)获取行方式总和,然后为每个标签调用withColumn()

labels = ['color', 'feeling']

sample_df.withColumn('total', sum([f.col(x) for x in labels]))\
    .withColumn('color', f.col('color')/f.col('total'))\
    .withColumn('feeling', f.col('feeling')/f.col('total'))\
    .select('word', 'color', 'feeling')\
    .show()

但是必须有一个更好的方法,而不是枚举每个可能的列。

更一般地说,我的问题是:

如何同时将任意转换(即当前行的函数)应用于多个列?

apache-spark pyspark apache-spark-sql pyspark-sql
1个回答
5
投票

this Medium post找到了答案。

首先为总数做一个列(如上所述),然后使用*运算符在select()中的标签上解压缩列表解析:

labels = ['color', 'feeling']
sample_df = sample_df.withColumn('total', sum([f.col(x) for x in labels]))

sample_df.select(
    'word', *[(f.col(col_name)/f.col('total')).alias(col_name) for col_name in labels]
).show()

链接帖子上显示的方法显示了如何将其概括为任意转换。

© www.soinside.com 2019 - 2024. All rights reserved.