假设您有一个具有各种类型列(string,double.)的dataframe以及在字符串类型列中表示“缺失值”的特殊值“想念”。
from pyspark.sql import SparkSession
import pandas as pd
spark = SparkSession.builder.getOrCreate()
pdf = pd.DataFrame([
[1, 'miss'],
[2, 'x'],
[None, 'y']
], columns=['intcol', 'strcol'])
df = spark.createDataFrame(data=pdf)我正在尝试计算每一列的未丢失值的数量,使用如下过滤:
col = df['strcol']
df.filter(col.isNotNull() & (col != 'miss')).show()它适用于string列:
+------+------+
|intcol|strcol|
+------+------+
| 2.0| x|
| NaN| y|
+------+------+但是,对于数值列,它过滤掉所有行:
col = df['intcol']
df.filter(col.isNotNull() & (col != 'miss')).show()+------+------+
|intcol|strcol|
+------+------+
+------+------+这似乎是因为数值列与字符串值的跨类型比较导致了所有空值:
df.select(df['intcol'] != 'miss').show()+---------------------+
|(NOT (intcol = miss))|
+---------------------+
| null|
| null|
| null|
+---------------------+我觉得这有点出乎意料(例如,1 != ''是真的,在“普通”Python中不是空的)
我的问题实际上是几个问题:
df.filter(~df['intcol'].isin(['miss']))做了这项工作,但我不知道这是否会降低效率?发布于 2019-01-31 11:33:34
我们先来说说原因。SQL是一个适用于DataFrame和SQL计算规则的DSL。每当您对不同类型的对象应用运算符时,都会根据预定义的规则在优先级较低的操作数上应用CAST操作。因此,在一般的数值类型中,具有更高的优先级(按照执行计划df.select(df['intcol'] != 'miss').explain(True)):
== Parsed Logical Plan ==
'Project [NOT (intcol#0 = miss) AS (NOT (intcol = miss))#12]
+- LogicalRDD [intcol#0, strcol#1], false被重写为
== Analyzed Logical Plan ==
(NOT (intcol = miss)): boolean
Project [NOT (intcol#0 = cast(miss as double)) AS (NOT (intcol = miss))#12]
+- LogicalRDD [intcol#0, strcol#1], false其中'miss'是CASTED到double,然后转换为NULL
== Optimized Logical Plan ==
Project [null AS (NOT (intcol = miss))#22]
+- LogicalRDD [intcol#0, strcol#1], false此操作数的强制转换是未定义的。
由于与NULL的等式也是未定义的- Difference between === null and isNull in Spark DataDrame - filter将产生一个空结果。
现在该如何解决这个问题。两种显式铸造:
df.filter(df['intcol'].cast("string") != 'miss')以及无效的安全相等:
df.filter(~df['intcol'].cast("string").eqNullSafe('miss'))应该能起作用。
另外,请注意,NaN值不是NULL,通过Pandas的转换是有损的- Pandas dataframe to Spark dataframe, handling NaN conversions to actual null?。
https://stackoverflow.com/questions/54458070
复制相似问题