我正在尝试将一些代码从pandas移植到(py)Spark。不幸的是,我已经失败了输入部分,我想读取二进制数据并将其放入Spark数据帧。
到目前为止,我正在使用来自numpy的fromfile
:
dt = np.dtype([('val1', '<i4'),('val2','<i4'),('val3','<i4'),('val4','f8')])
data = np.fromfile('binary_file.bin', dtype=dt)
data=data[1:] #throw away header
df_bin = pd.DataFrame(data, columns=data.dtype.names)
但是对于Spark我找不到怎么做。到目前为止我的解决方法是使用csv-Files而不是二进制文件,但这不是一个理想的解决方案。我知道我不应该使用numpy的fromfile
和火花。
如何读取已加载到hdfs的二进制文件?
我试过像
这样的东西fileRDD=sc.parallelize(['hdfs:///user/bin_file1.bin','hdfs:///user/bin_file2.bin])
fileRDD.map(lambda x: ???)
但它给了我一个No such file or directory
错误。
我见过这个问题: spark in python: creating an rdd by loading binary data with numpy.fromfile 但这只有在我将文件存储在驱动程序节点的主页时才有效。
答案 0 :(得分:3)
因此,对于那些以Spark开头并且绊倒uopn二进制文件的人来说,这就是我解决它的方法:
dt=np.dtype([('idx_metric','>i4'),('idx_resource','>i4'),('date','>i4'),
('value','>f8'),('pollID','>i2')])
schema=StructType([StructField('idx_metric',IntegerType(),False),
StructField('idx_resource',IntegerType(),False),
StructField('date',IntegerType),False),
StructField('value',DoubleType(),False),
StructField('pollID',IntegerType(),False)])
filenameRdd=sc.binaryFiles('hdfs://nameservice1:8020/user/*.binary')
def read_array(rdd):
#output=zlib.decompress((bytes(rdd[1])),15+32) # in case also zipped
array=np.frombuffer(bytes(rdd[1])[20:],dtype=dt) # remove Header (20 bytes)
array=array.newbyteorder().byteswap() # big Endian
return array.tolist()
unzipped=filenameRdd.flatMap(read_array)
bin_df=sqlContext.createDataFrame(unzipped,schema)
现在,您可以使用数据框在Spark中执行任何您想要的任何花哨的东西。
答案 1 :(得分:2)
编辑: 请查看此处提到的sc.binaryFiles的使用: https://stackoverflow.com/a/28753276/5088142
尝试使用:
hdfs://machine_host_name:8020/user/bin_file1.bin
core-site.xml
中 fs.defaultFS 中的主机名答案 2 :(得分:1)
从 Spark 3.0 开始,Spark 支持二进制文件数据源,它读取二进制文件并将每个文件转换为包含文件原始内容和元数据的单个记录。
https://spark.apache.org/docs/latest/sql-data-sources-binaryFile.html
答案 3 :(得分:0)
我最近做过这样的事情:
from struct import unpack_from
# creates an RDD of binaryrecords for determinted record length
binary_rdd = sc.binaryRecords("hdfs://" + file_name, record_length)
# map()s each binary record to unpack() it
unpacked_rdd = binary_rdd.map(lambda record: unpack_from(unpack_format, record))
# registers a data frame with this schema; registerTempTable() it as table_name
raw_df = sqlc.createDataFrame(unpacked_rdd, sparkSchema)
raw_df.registerTempTable(table_name)
其中unpack_format和sparkSchema必须是&#34;同步&#34;。
unpack_format是Python的unpack()和unpack_from()函数使用的格式,如 https://docs.python.org/2/library/struct.html#format-characters
sparkSchema是一个定义数据框架构的变量。请参阅https://spark.apache.org/docs/1.6.2/api/python/pyspark.sql.html#pyspark.sql.SQLContext.createDataFrame
我有一个动态生成unpack_format和sparkSchema变量的脚本;两者同时进行。 (它是更大代码库的一部分,因此不在此处发布以获取可读性)
unpack_format和sparkSchema可以定义如下,例如
from pyspark.sql.types import *
unpack_format = '<' # '<' means little-endian: https://docs.python.org/2/library/struct.html#byte-order-size-and-alignment
sparkSchema = StructType()
record_length = 0
unpack_format += '35s' # 35 bytes that represent a character string
sparkSchema.add("FirstName", 'string', True) # True = nullable
record_length += 35
unpack_format += 'H' # 'H' = unsigned 2-byte integer
sparkSchema.add("ZipCode", 'integer', True)
record_length += 2
# and so on for each field..