【发布时间】:2018-08-21 22:53:14
【问题描述】:
我有一个数据集,其中包含一个未知(且不友好)编码的 ID 字段。我可以使用普通 python 读取单个列,并验证多个数据集的值是否不同且一致(即它可以用作连接的主键)。
使用spark.read.csv 加载文件时,spark 似乎正在将该列转换为utf-8。但是,一些多字节序列被转换为 Unicode 字符 U+FFFD REPLACEMENT CHARACTER.(EF BF BD 十六进制)。
有没有办法强制 Spark 将列读取为字节而不是字符串?
这是一些可用于重新创建我的问题的代码(让列 a 成为 ID 字段):
使用示例数据创建文件
data = [
(bytes(b'\xba\xed\x85\x8e\x91\xd4\xc7\xb0'), '1', 'a'),
(bytes(b'\xba\xed\x85\x8e\x91\xd4\xc7\xb1'), '2', 'b'),
(bytes(b'\xba\xed\x85\x8e\x91\xd4\xc7\xb2'), '3', 'c')
]
with open('sample.csv', 'wb') as f:
header = ["a", "b", "c"]
f.write(",".join(header)+"\n")
for d in data:
f.write(",".join(d) + "\n")
使用 Pandas 阅读
import pandas as pd
df = pd.read_csv("sample.csv", converters={"a": lambda x: x.encode('hex')})
print(df)
# a b c
#0 baed858e91d4c7b0 1 a
#1 baed858e91d4c7b1 2 b
#2 baed858e91d4c7b2 3 c
尝试使用 Spark 读取同一个文件
spark_df = spark.read.csv("sample.csv", header=True)
spark_df.show()
#+-----+---+---+
#|a |b |c |
#+-----+---+---+
#|�텎��ǰ|1 |a |
#|�텎��DZ|2 |b |
#|�텎��Dz|3 |c |
#+-----+---+---+
哎呀!好的,那转换成hex怎么样?
import pyspark.sql.functions as f
spark_df.withColumn("a", f.hex("a")).show(truncate=False)
#+----------------------------+---+---+
#|a |b |c |
#+----------------------------+---+---+
#|EFBFBDED858EEFBFBDEFBFBDC7B0|1 |a |
#|EFBFBDED858EEFBFBDEFBFBDC7B1|2 |b |
#|EFBFBDED858EEFBFBDEFBFBDC7B2|3 |c |
#+----------------------------+---+---+
(在此示例中,值是不同的,但在我的较大文件中并非如此)
如你所见,值是close,但部分字节已被EFBFBD替换
有没有办法在 Spark 中读取文件(可能使用rdd?),这样我的输出看起来就像熊猫版本:
#+----------------+---+---+
#|a |b |c |
#+----------------+---+---+
#|baed858e91d4c7b0|1 |a |
#|baed858e91d4c7b1|2 |b |
#|baed858e91d4c7b2|3 |c |
#+----------------+---+---+
我已尝试强制转换为 byte 并指定架构,以便此列为 ByteType(),但这不起作用。
编辑
我使用的是 Spark v 2.1。
【问题讨论】:
-
您找到了解决上述问题的任何方法。我遇到了类似的问题
-
能告诉我你找到的解决方案吗?
标签: apache-spark encoding pyspark apache-spark-sql