簡體   English   中英

如何將二進制文件從 hdfs 讀入 Spark 數據幀?

[英]How can I read in a binary file from hdfs into a Spark dataframe?

我正在嘗試將一些代碼從 Pandas 移植到 (py)Spark。 不幸的是,我已經在輸入部分失敗了,我想在其中讀取二進制數據並將其放入 Spark Dataframe。

到目前為止,我正在使用來自 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與 spark 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: create an rdd by loading binary data with numpy.fromfile但只有當我將文件存儲在驅動程序節點的主目錄中時才有效。

所以,對於像我這樣從 Spark 開始並偶然發現二進制文件的人。 這是我解決它的方法:

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 中做任何你想做的事情。

編輯:請查看這里提到的 sc.binaryFiles 的使用: https ://stackoverflow.com/a/28753276/5088142


嘗試使用:

hdfs://machine_host_name:8020/user/bin_file1.bin

您是core-site.xmlfs.defaultFS中的主機名

從 Spark 3.0 開始,Spark 支持二進制文件數據源,它讀取二進制文件並將每個文件轉換為包含文件原始內容和元數據的單個記錄。

https://spark.apache.org/docs/latest/sql-data-sources-binaryFile.html

我最近做了這樣的事情:

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 必須“同步”。

我有一個動態生成 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..

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM