在pyspark中创建派生列时如何解决以下问题?

时间:2019-04-22 15:41:51

标签: python-3.x apache-spark pyspark apache-spark-sql pyspark-sql

我正在尝试根据字典中给出的数据对数据框中的特定列进行分箱。

以下是我使用的数据框:

df

SNo,Name,CScore
1,x,700
2,y,850
3,z,560
4,a,578
5,b,456
6,c,678

我创建了以下函数,如果我单独使用它,它可以正常工作。


def binning(column,dict):
    finalColumn=[]
    lent = len(column)
    for i in range(lent):
        for j in range(len(list(dict))):
            if( int(column[i]) in range(list(dict)[j][0],list(dict)[j][1])):
                finalColumn.append(dict[list(dict)[j]])
    return finalColumn

我在下面的语句中使用了上面的功能。

newDf = df.withColumn("binnedColumn",binning(df.select("CScore").rdd.flatMap(lambda x: x).collect(),{(1,400):'Low',(401,900):'High'}))

我收到以下错误:

回溯(最近通话最近):   文件“”,第1行,位于   文件“ C:\ spark_2.4 \ python \ pyspark \ sql \ dataframe.py”,第1988行,withColumn     assert isinstance(col,Column),“ col应该是列” AssertionError:col应该是Column

解决这个问题的任何帮助都会有很大帮助。谢谢。

1 个答案:

答案 0 :(得分:0)

让我们从创建数据开始:

rdd = sc.parallelize([[1,"x",700],[2,"y",850],[3,"z",560],[4,"a",578],[5,"b",456],[6,"c",678]])
df = rdd.toDF(["SNo","Name","CScore"])
>>> df.show()
+---+----+------+
|SNo|Name|CScore|
+---+----+------+
|  1|   x|   700|
|  2|   y|   850|
|  3|   z|   560|
|  4|   a|   578|
|  5|   b|   456|
|  6|   c|   678|
+---+----+------+

如果您的最终目标是像您的示例一样提供binning_dictionary,则查找相应的分类值。 udf是解决方案。

以下是您的正常功能。

bin_lookup = {(1,400):'Low',(401,900):'High'}
def binning(value, lookup_dict=bin_lookup):
    for key in lookup_dict.keys():
        if key[0] <= value <= key[1]:
             return lookup_dict[key]

注册为udf并通过数据框运行它:

from pyspark.sql.functions import udf
from pyspark.sql.types import StringType

binning_udf = udf(binning, StringType())
>>> df.withColumn("binnedColumn", binning_udf("CScore")).show()
+---+----+------+------------+
|SNo|Name|CScore|binnedColumn|
+---+----+------+------------+
|  1|   x|   700|        High|
|  2|   y|   850|        High|
|  3|   z|   560|        High|
|  4|   a|   578|        High|
|  5|   b|   456|        High|
|  6|   c|   678|        High|
+---+----+------+------------+

直接应用于rdd:

>>> rdd.map(lambda row: binning(row[-1], bin_lookup)).collect()
['High', 'High', 'High', 'High', 'High', 'High']