Sql 筛选pyspark dataframe中的行并创建包含结果的新列

Sql 筛选pyspark dataframe中的行并创建包含结果的新列,sql,pyspark,user-defined-functions,Sql,Pyspark,User Defined Functions,所以我试图确定周日发生在旧金山市中心边界内的犯罪。我的想法是首先编写一个UDF来标记每个犯罪是否在我确定为市中心的区域内,如果发生在该区域内,那么它将有一个1和0的标签(如果不是)。之后,我尝试创建一个新列来存储这些结果。我尽我最大的努力写下我能写的一切,但由于某种原因,它就是不起作用。以下是我编写的代码: from pyspark.sql.types import BooleanType from pyspark.sql.functions import udf def filter_dt(

所以我试图确定周日发生在旧金山市中心边界内的犯罪。我的想法是首先编写一个UDF来标记每个犯罪是否在我确定为市中心的区域内,如果发生在该区域内,那么它将有一个1和0的标签(如果不是)。之后,我尝试创建一个新列来存储这些结果。我尽我最大的努力写下我能写的一切,但由于某种原因,它就是不起作用。以下是我编写的代码:

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

def filter_dt(x,y):
  if (((x < -122.4213) & (x > -122.4313)) & ((y > 37.7540) & (y < 37.7740))):
    return '1'
  else:
    return '0'

schema = StructType([StructField("isDT", BooleanType(), False)])
filter_dt_boolean = udf(lambda row: filter_dt(row[0], row[1]), schema)

#First, pick out the crime cases that happens on Sunday BooleanType()
q3_sunday = spark.sql("SELECT * FROM sf_crime WHERE DayOfWeek='Sunday'")
#Then, we add a new column for us to filter out(identify) if the crime is in DT
q3_final = q3_result.withColumn("isDT", filter_dt(q3_sunday.select('X'),q3_sunday.select('Y')))
我得到的错误是:


我的猜测是,我现在使用的udf不支持将整个列作为要比较的输入,但我不知道如何修复它以使其工作。请帮忙!谢谢大家!

一个样本数据会有所帮助。目前,我假设您的数据如下所示:

+----+---+---+
|val1|  x|  y|
+----+---+---+
|  10|  7| 14|
|   5|  1|  4|
|   9|  8| 10|
|   2|  6| 90|
|   7|  2| 30|
|   3|  5| 11|
+----+---+---+
然后您不需要自定义项,因为您可以使用when函数进行评估

import pyspark.sql.functions as F
tst= sqlContext.createDataFrame([(10,7,14),(5,1,4),(9,8,10),(2,6,90),(7,2,30),(3,5,11)],schema=['val1','x','y'])
tst_res = tst.withColumn("isdt",F.when(((tst.x.between(4,10))&(tst.y.between(11,20))),1).otherwise(0))This will give the result
   tst_res.show()
+----+---+---+----+
|val1|  x|  y|isdt|
+----+---+---+----+
|  10|  7| 14|   1|
|   5|  1|  4|   0|
|   9|  8| 10|   0|
|   2|  6| 90|   0|
|   7|  2| 30|   0|
|   3|  5| 11|   1|
+----+---+---+----+
如果我的数据有误,但仍然需要将多个值传递给udf,那么必须将其作为数组或结构传递。我喜欢结构

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

@udf(IntegerType())
def check_data(row):
    if((row.x in range(4,5))&(row.y in range(1,20))):
        return(1)
    else:
        return(0)
tst_res1 = tst.withColumn("isdt",check_data(F.struct('x','y')))

结果是一样的。但最好避免使用自定义项,使用spark内置函数,因为spark catalyst无法理解自定义项中的逻辑,也无法对其进行优化。

请尝试更改最后一行,如下所示-

从pyspark.sql.functions导入col q3_final=q3_result.with columnisdt,filter_dtcol'X',col'Y'