PySpark Dataframe -将字符串Map到数字

wlp8pajw  于 2022-09-21  发布在  Spark
关注(0)|答案(2)|浏览(200)

我正在寻找一种方法来转换给定的数据列,在本例中为字符串,并将它们转换为数字表示形式。例如,我有一个包含值的字符串的 Dataframe :

+------------+
|    level   |
+------------+
|      Medium|
|      Medium|
|      Medium|
|        High|
|      Medium|
|      Medium|
|         Low|
|         Low|
|        High|
|         Low|
|         Low|

我想创建一个新列,在其中将这些值转换为:

"High"= 1, "Medium" = 2, "Low" = 3

+------------+
|   level_num|
+------------+
|           2|
|           2|
|           2|
|           1|
|           2|
|           2|
|           3|
|           3|
|           1|
|           3|
|           3|

我尝试定义一个函数并对 Dataframe 执行Foreach操作,如下所示:

def f(x): 
    if(x == 'Medium'):
       return 2
    elif(x == "Low"):
       return 3
    else:
       return 1

 a = df.select("level").rdd.foreach(f)

但这将返回一个“None”类型。有什么想法吗?一如既往的感谢你的帮助!

zzlelutf

zzlelutf1#

您当然可以按照您一直尝试的方法来完成--您将需要一个map操作,而不是foreach

spark.version

# u'2.2.0'

from pyspark.sql import Row

# toy data:

df = spark.createDataFrame([Row("Medium"),
                              Row("High"),
                              Row("High"),
                              Row("Low")
                             ],
                              ["level"])
df.show()

# +------+

# | level|

# +------+

# |Medium|

# |  High|

# |  High|

# |   Low|

# +------+

使用您的f(x)和这些玩具数据,我们可以获得:

df.select("level").rdd.map(lambda x: f(x[0])).collect()

# [2, 1, 1, 3]

再来一张map就会给你一个 Dataframe :

df.select("level").rdd.map(lambda x: f(x[0])).map(lambda x: Row(x)).toDF(["level_num"]).show()

# +---------+

# |level_num|

# +---------+

# |        2|

# |        1|

# |        1|

# |        3|

# +---------+

但最好不要调用临时中间RDD,而是使用 Dataframe 函数when而不是f(x)

from pyspark.sql.functions import col, when

df.withColumn("level_num", when(col("level")=='Medium', 2).when(col("level")=='Low', 3).otherwise(1)).show()

# +------+---------+

# | level|level_num|

# +------+---------+

# |Medium|        2|

# |  High|        1|

# |  High|        1|

# |   Low|        3|

# +------+---------+
pkmbmrz7

pkmbmrz72#

另一种方法是使用内置的Python词典来表示Spark>=2.4的Map。

然后使用Spark map和map_from_arrares实现基于键的搜索机制,以填充level_num字段:

from pyspark.sql.functions import lit, map_from_arrays, array

_dict = {"High":1, "Medium":2, "Low":3}

df = spark.createDataFrame([
["Medium"], ["Medium"], ["Medium"], ["High"], ["Medium"], ["Medium"], ["Low"], ["Low"], ["High"]
], ["level"])

keys = array(list(map(lit, _dict.keys()))) # or alternatively [lit(k) for k in _dict.keys()]
values = array(list(map(lit, _dict.values())))
_map = map_from_arrays(keys, values)

df.withColumn("level_num", _map.getItem(col("level"))) # or element_at(_map, col("level"))

# +------+---------+

# | level|level_num|

# +------+---------+

# |Medium|        2|

# |Medium|        2|

# |Medium|        2|

# |  High|        1|

# |Medium|        2|

# |Medium|        2|

# |   Low|        3|

# |   Low|        3|

# |  High|        1|

# +------+---------+

相关问题