Pyspark - 在特定列上运行的Lambda表达式

时间:2017-09-03 17:19:17

标签: random lambda pyspark spark-dataframe

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

+---------------+---+---+---+---+---+---+
|         Entity| id|  7| 15| 19| 21| 27|
+---------------+---+---+---+---+---+---+
|              a|  0|  0|  1|  0|  0|  0|
|              b|  1|  0|  0|  0|  1|  0|
|              c|  2|  0|  0|  0|  1|  0|
|              d|  3|  2|  0|  0|  0|  0|
|              e|  4|  0|  3|  0|  0|  0|
|              f|  5|  0| 25|  0|  0|  0|
|              g|  6|  2|  0|  0|  0|  0|

我想在每个列中的所有元素中添加0到1之间的随机值,实体和实体ID。实体和实体之后可以有任意数量的列。 id(在这种情况下有5个,但可能有100个,或1000个或更多)。

这是我到目前为止所拥有的:

 random_df = data.select("*").rdd.map(
     lambda x, r=random: [Row(str(row)) if isinstance(row, unicode) else 
     Row(float(r.random() + row)) for row in x]).toDF(data.columns)

但是,这也会在id列中添加一个随机值。通常情况下,如果我之前知道元素的数量,并且我知道它们将被修复,我可以使用

在lambda表达式中明确地调用它们。
data.select("*").rdd.map(lambda (a,b,c,d,e,f,g): 
         Row(a,b, r.random() + c r.random() + d, r.random() + e, r.random() 
               + f, r.random() + g))

但是,不幸的是,由于不知道我将提前有多少列,这不会起作用。想法?我真的很感激帮助!

编辑:我还应该注意'id'是调用的结果:

data = data.withColumn("id", monotonically_increasing_id())

添加此编辑,因为我尝试将列'id'转换为StringType,以便我的'isinstance(row,unicode)'会触发,但我没有成功。以下代码:

data = data.withColumn("id", data['id'].cast(StringType)

结果:

raise TypeError("unexpected type: %s" % type(dataType))
TypeError: unexpected type: <class 'pyspark.sql.types.DataTypeSingleton'>

1 个答案:

答案 0 :(得分:2)

您应该在.cast("string")列上尝试id

import random
import pyspark.sql.functions as f
from pyspark.sql.types import Row

df = sc.parallelize([
    ['a', 0, 1, 0, 0, 0],
    ['b', 0, 0, 0, 1, 0],
    ['c', 0, 0, 0, 1, 0],
    ['d', 2, 0, 0, 0, 0],
    ['e', 0, 3, 0, 0, 0],
    ['f', 0, 25,0, 0, 0],
    ['g', 2, 0, 0, 0, 0],
]).toDF(('entity', '7', '15', '19', '21', '27'))
df = df.withColumn("id", f.monotonically_increasing_id())
df = df.withColumn("id_string", df["id"].cast("string")).drop("id")
df.show()

random_df = df.select("*").rdd.map(
     lambda x, r=random: [Row(str(row)) if isinstance(row, unicode) else
     Row(float(r.random() + row)) for row in x]).toDF(df.columns)
random_df.show()

希望这有帮助!