如何在Pyspark Dataframe 中使用带日期列的IsNull()条件?

o8x7eapl  于 2023-01-02  发布在  Apache
关注(0)|答案(3)|浏览(207)

我们如何在Pyspark中使用日期类型列的isNull()条件。我需要更新列名REGISTER_DATE,当它为空并且还满足其他条件时?

data = [{"REGISTER_DATE": '', "FORM_DATE": '16-12-2022', "GENDER": Female, "Truth": True},
{"REGISTER_DATE": '13-09-2022', "FORM_DATE": '06-12-2022',"GENDER": Female"Truth":True},
{"REGISTER_DATE": '', "FORM_DATE": '20-12-2022', "GENDER": Female, "Truth": True},
{"REGISTER_DATE": '', "FORM_DATE": '18-12-2022', "GENDER": Female, "Truth": True}]

from pyspark.sql import SparkSession
spark = SparkSession.builder.getOrCreate()
create_df = spark.createDataFrame(data)

FORM_DATEREGISTER_DATE列为日期数据类型,性别为字符串
我正在尝试的查询是:

create_df=create_df.withColumn('REGISTER_DATE',F.when((col('REGISTER_DATE').isNull()) & 
    (col('FORM_DATE') !='') & (col('GENDER')== 'FEMALE'), create_df.FORM_DATE)
    .otherwise(create_df['REGISTER_DATE']))

查询运行正常,但不更新列REGISTER_DATE,即使源文件中存在条件。
据我所知,isNulldate 类型列一起使用可能无效。如果条件匹配,我希望使用FORM_DATE列值更新REGISTER_DATE列空值。

xfyts7mz

xfyts7mz1#

假设你有一个data

+-------------+----------+------+-----+
|REGISTER_DATE|FORM_DATE |GENDER|TRUTH|
+-------------+----------+------+-----+
|null         |2022-12-16|Female|True |
|2022-09-13   |2022-12-06|Female|True |
|null         |2022-12-20|Female|True |
|null         |2022-12-18|Female|True |
+-------------+----------+------+-----+

使用此架构:

root
 |-- REGISTER_DATE: date (nullable = true)
 |-- FORM_DATE: date (nullable = true)
 |-- GENDER: string (nullable = true) <-- doesn't matter
 |-- TRUTH: string (nullable = true)  <-- doesn't matter

如果你的类型是date(在REGISTER_DATEFORM_DATE列上),它们将永远不会有空字符串; date类型是有效日期或null
如果我们这样做:

data = data.withColumn("REGISTER_DATE",
  when(col("REGISTER_DATE").isNull, col("FORM_DATE"))
    .otherwise(col("REGISTER_DATE")))

然后,我们将得到以下输出:

+-------------+----------+------+-----+
|REGISTER_DATE|FORM_DATE |GENDER|TRUTH|
+-------------+----------+------+-----+
|2022-12-16   |2022-12-16|Female|True |
|2022-09-13   |2022-12-06|Female|True |
|2022-12-20   |2022-12-20|Female|True |
|2022-12-18   |2022-12-18|Female|True |
+-------------+----------+------+-----+

在您的示例中,您用空字符串填充数据,并声称它们属于date类型,但实际情况并非如此,您的&条件使整个语句变为false,这可能是因为您试图将date类型与空字符串进行比较,但实际情况并非如此。
您只需要确保REGISTER_DATEFORM_DATEdate而不是string,并且铸造(如果您将来这样做的话)是正确的。
祝你好运!

wvyml7n5

wvyml7n52#

使用你提供的数据,它正在创建字符串数据类型的列。2如果是这种情况,那么对于空字符串,你必须使用==''条件。3记住,空字符串不等于null。4然而,如果你的意思是说你的实际数据具有日期数据类型的列,并且这个示例代码/数据具有字符串是不正确的,那么我们不能在spark中的日期数据类型的列中插入空字符串。
您的代码是正确的,并且在以下情况下无需任何修改即可正常工作
1.你的数据是正确的日期数据类型,而不是以字符串数据类型存储的日期。
1.值是正确的null而不是空字符串。
screenshot showing datatype of the dataframe created from data provided in question
screenshot showing it works with stringDatatType=='' & DateType can not accept object '' in type

g2ieeal7

g2ieeal73#

我希望它适用于您的解决方案,将REGISTER_DATE和FORM_DATE转换为datetype,然后实现您的逻辑或转换为日期,然后使用合并函数,就像在SQL中一样。我将REGISTER_DATE和FORM_DATE转换回字符串,因为如果它包含任何依赖项。

import findspark
findspark.init()
findspark.find()
from pyspark.sql import *
from  pyspark.sql.functions import *
data = [{"REGISTER_DATE": '', "FORM_DATE": '16-12-2022', "GENDER": 'Female', "Truth": True},
{"REGISTER_DATE": '13-09-2022', "FORM_DATE": '06-12-2022',"GENDER": 'Female', "Truth":True},
{"REGISTER_DATE": '', "FORM_DATE": '20-12-2022', "GENDER": 'Female', "Truth": True},
{"REGISTER_DATE": '', "FORM_DATE": '18-12-2022', "GENDER": 'Female', "Truth": True}]# Define Schema without infering spark
spark = SparkSession.builder.getOrCreate()
create_df = spark.createDataFrame(data)
print('Before converting to date and handling null')
create_df.printSchema()
create_df.show()
create_df = create_df.withColumn('FORM_DATE', to_date(col('FORM_DATE'), 'dd-MM-yyyy'))
create_df = create_df.withColumn('REGISTER_DATE', to_date(col('REGISTER_DATE'), 'dd-MM-yyyy'))
# Solution 1:
# create_df = create_df.withColumn('REGISTER_DATE',when((col('REGISTER_DATE').isNull()) & 
#     (col('FORM_DATE').isNotNull()) & (col('GENDER')== 'Female'), create_df.FORM_DATE)
#     .otherwise(create_df['REGISTER_DATE']))
# Solution 2:
create_df = create_df.withColumn('REGISTER_DATE', coalesce('REGISTER_DATE', 'FORM_DATE'))
# convert back to string 
create_df = create_df.withColumn('FORM_DATE', col('FORM_DATE').cast('string'))
create_df = create_df.withColumn('REGISTER_DATE', col('REGISTER_DATE').cast('string'))
print('After converting to date and handling null')
create_df.printSchema()
create_df.show()

相关问题