我使用的是Spark2.1,使用的是pyscripting
问题陈述:有一个场景,需要将多个列作为输入传递,然后返回一个列作为输出,这是我输入的3列的数据。
A、b、c
S S S
S NS
S NS S
S S NS
NS S
我的输出必须如下
a、b、c、d
S S
NS NS
S NS S
S S NS
NS S NS
我试图注册一个UDF来传递这3列a,b,c作为输入,并返回d列作为输出,在这里,a,b,c,d是列名。
我发现很难得到下面的输出是使用的语法
def return_string(x):
if [x.a=='s' & x.b=='S' & x.c=='s']
return 'S'
else if[x.a=='s' & x.b=='NS' & x.c=='s']
return 'S'
else if[x.a=='s' & x.b=='S' & x.c=='NS']
return 'NS;
func= udf(returnstring,types.StringType())有谁能帮我完成这个逻辑吗。
发布于 2017-08-23 19:56:24
我试图使用内置的withColumn和when函数来完成它:
from pyspark.sql.functions import col, when, lit
df.withColumn('d', when(
((col('A') == 'S') & (col('B') == 'S') & (col('C')=='S'))
| ((col('A') == 'S') & (col('B') == 'NS') & (col('C')=='S'))
, lit('S')
).otherwise(lit('NS'))
).show()这也是假设这两个值是互斥的(因此otherwise)
发布于 2017-08-23 19:49:45
它应该是:
@udf
def return_string(a, b, c):
if a == 's' and b == 'S' and c == 's':
return 'S'
if a == 's' and b == 'NS' and c == 's':
return 'S'
if a == 's' and b == 'S' and c == 'NS':
return 'NS'
df = sc.parallelize([('s', 'S', 'NS'), ('?', '?', '?')]).toDF(['a', 'b', 'c'])
df.withColumn('result', return_string('a', 'b', 'c')).show()
## +---+---+---+------+
## | a| b| c|result|
## +---+---+---+------+
## | s| S| NS| NS|
## | ?| ?| ?| null|
## +---+---+---+------+struct传递)。and而不是& (您计算逻辑表达式而不是&表达式)。就我个人而言,我会跳过所有的ifs并使用简单的dict
@udf
def return_string(a, b, c):
mapping = {
('s', 'S', 's'): 'S',
('s', 'NS' 's'): 'S',
('s', 'S', 'NS'): 'NS',
}
return mapping.get((a, b, c))根据您的要求调整条件。
总的来说,您应该更喜欢如Steven提供的the excellent answer中所示的SQL表达式(您可以使用when(..., ...).when(..., ...)链接多个条件)。
https://stackoverflow.com/questions/45847870
复制相似问题