如何将大熊猫数据框保存到hdfs?

时间:2017-11-20 13:19:03

标签: python pandas apache-spark pyarrow apache-arrow

我正在使用pandas和spark数据帧。数据帧总是非常大(> 20 GB),标准火花功能不足以满足这些尺寸。目前我正在将我的pandas数据帧转换为这样的火花数据帧:

dataframe = spark.createDataFrame(pandas_dataframe)  

我进行了这种转换,因为使用spark将数据帧写入hdfs非常简单:

dataframe.write.parquet(output_uri, mode="overwrite", compression="snappy")

但是对于大于2 GB的数据帧,转换失败了。 如果我将火花数据帧转换为pandas,我可以使用pyarrow:

// temporary write spark dataframe to hdfs
dataframe.write.parquet(path, mode="overwrite", compression="snappy")

// open hdfs connection using pyarrow (pa)
hdfs = pa.hdfs.connect("default", 0)
// read parquet (pyarrow.parquet (pq))
parquet = pq.ParquetDataset(path_hdfs, filesystem=hdfs)
table = parquet.read(nthreads=4)
// transform table to pandas
pandas = table.to_pandas(nthreads=4)

// delete temp files
hdfs.delete(path, recursive=True)

这是从spark到pandas的快速转换,它也适用于大于2 GB的数据帧。我还没有办法找到另一种方法。意思是有一个熊猫数据框,我在pyarrow的帮助下变换为火花。问题是我真的无法找到如何将pandas数据帧写入hdfs。

我的熊猫版:0.19.0

4 个答案:

答案 0 :(得分:5)

  

意思是拥有一个pandas数据帧,我在pyarrow的帮助下转换为spark。

pyarrow.Table.fromPandas是您要寻找的功能:

Table.from_pandas(type cls, df, bool timestamps_to_ms=False, Schema schema=None, bool preserve_index=True)

Convert pandas.DataFrame to an Arrow Table
import pyarrow as pa

pdf = ...  # type: pandas.core.frame.DataFrame
adf = pa.Table.from_pandas(pdf)  # type: pyarrow.lib.Table

结果可以直接写入Parquet / HDFS,而无需通过Spark传递数据:

import pyarrow.parquet as pq

fs  = pa.hdfs.connect()

with fs.open(path, "wb") as fw
    pq.write_table(adf, fw)

另见

Spark说明

此外,因为createDataFrameSPARK-20791 - Use Apache Arrow to Improve Spark createDataFrame from Pandas.DataFrame)中直接支持Spark 2.3(当前主控)箭头。它uses SparkContext.defaultParallelism to compute number of chunks因此您可以轻松控制各批次的大小。

最后,defaultParallelism可用于控制使用标准_convert_from_pandas生成的分区数量,从而有效地将切片大小减小到更易于管理的范围。

不幸的是,这些不太可能解决您的current memory problems。两者都依赖于parallelize,因此将所有数据存储在驱动程序节点的内存中。切换到箭头或调整配置只能加速进程或地址块大小限制。

在实践中,只要您使用本地Pandas DataFrame作为输入,我就没有理由在此处切换到Spark。这种情况下最严重的瓶颈是驱动程序的网络I / O和分发数据不能解决这个问题。

答案 1 :(得分:0)

来自https://issues.apache.org/jira/browse/SPARK-6235

  

支持并行化大于2GB的R data.frame

已解决。

来自https://pandas.pydata.org/pandas-docs/stable/r_interface.html

  

将DataFrame转换为R对象

您可以将pandas数据帧转换为R data.frame

所以也许变换熊猫 - > R - > Spark - > HDFS?

答案 2 :(得分:0)

另一种方法是将pandas数据框转换为spark数据框(使用pyspark),然后使用save命令将其保存到hdfs。 例子

    df = pd.read_csv("data/as/foo.csv")
    df[['Col1', 'Col2']] = df[['Col2', 'Col2']].astype(str)
    sc = SparkContext(conf=conf)
    sqlCtx = SQLContext(sc)
    sdf = sqlCtx.createDataFrame(df)

此处astype将列的类型从object更改为string。这样可以避免出现异常情况,因为火花无法弄清熊猫类型object。但是请确保这些列确实是字符串类型。

现在将df保存在hdfs中:

    sdf.write.csv('mycsv.csv')

答案 3 :(得分:-1)

黑客可能是从大型数据帧创建N个pandas数据帧(每个小于2 GB)(水平分区)并创建N个不同的spark数据帧,然后合并(Union)它们以创建最后一个写入HDFS。我假设您的主机功能强大,但您也可以使用运行Spark的集群。