熊猫数据框到Spark数据框,是否将NaN转换为实际的null?
问题内容:
我想将数据框从熊猫转换为Spark,并且正在使用spark_context.createDataFrame()
创建数据框的方法。我还在方法中指定了架构createDataFrame()
。
我想知道的是如何处理特殊情况。例如,当转换为Spark数据帧时,熊猫中的 NaN 最终为字符串“
NaN”。我正在寻找如何获取实际的空值而不是“ NaN”的方法。
问题答案:
TL; DR 现在最好的选择是完全跳过熊猫。
问题的根源是熊猫不如Spark SQL富有表现力。Spark提供NULL
(从SQL的意义上说是缺失值)和NaN
(数字不是数字)。
另一只手的熊猫没有可用于表示缺失值的本机值。因此,它使用占位符(例如NaN
/NaT
或)Inf
,这些占位符与Spark的实际区别不大NaNs
,Infs
并且转换规则取决于列类型。唯一的例外是object
可以包含None
值的列(通常是字符串)。您可以从文档中了解有关处理缺失值的更多信息。
例如,当转换为Spark数据帧时,熊猫中的NaN最终为字符串“ NaN”。
这实际上是不正确的。取决于输入列的类型。如果column显示NaN
它很可能不是数字值,则不是纯字符串:
from pyspark.sql.functions import isnan, isnull
pdf = pd.DataFrame({
"x": [1, None], "y": [None, "foo"],
"z": [pd.Timestamp("20120101"), pd.Timestamp("NaT")]
})
sdf = spark.createDataFrame(pdf)
sdf.show()
+---+----+-------------------+
| x| y| z|
+---+----+-------------------+
|1.0|null|2012-01-01 00:00:00|
|NaN| foo| null|
+---+----+-------------------+
sdf.select([
f(c) for c in sdf.columns for f in [isnan, isnull]
if (f, c) != (isnan, "z") # isnan cannot be applied to timestamp
]).show()
+--------+-----------+--------+-----------+-----------+
|isnan(x)|(x IS NULL)|isnan(y)|(y IS NULL)|(z IS NULL)|
+--------+-----------+--------+-----------+-----------+
| false| false| false| true| false|
| true| false| false| false| true|
+--------+-----------+--------+-----------+-----------+
实际上,并行化的本地集合(包括Pandas对象)在简单的测试和玩具示例之外的重要性可以忽略不计,因此您始终可以手动转换数据(跳过可能的Arrow优化):
import numpy as np
spark.createDataFrame([
tuple(
None if isinstance(x, (float, int)) and np.isnan(x) else x
for x in record.tolist())
for record in pdf.to_records(index=False)
], pdf.columns.tolist()).show()
+----+----+-------------------+
| x| y| z|
+----+----+-------------------+
| 1.0|null|1325376000000000000|
|null| foo| null|
+----+----+-------------------+
如果缺少/不是数字的歧义不是问题,那么只需照常加载数据并替换为Spark。
from pyspark.sql.functions import col, when
sdf.select([
when(~isnan(c), col(c)).alias(c) if t in ("double", "float") else c
for c, t in sdf.dtypes
]).show()
+----+----+-------------------+
| x| y| z|
+----+----+-------------------+
| 1.0|null|2012-01-01 00:00:00|
|null| foo| null|
+----+----+-------------------+