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

Python 如何将大熊猫数据帧保存到hdfs?,python,pandas,apache-spark,pyarrow,apache-arrow,Python,Pandas,Apache Spark,Pyarrow,Apache Arrow,我和熊猫以及spark数据帧一起工作。数据帧总是非常大(>20GB),标准spark函数不足以满足这些大小。目前,我正在将我的pandas数据帧转换为spark数据帧,如下所示: dataframe = spark.createDataFrame(pandas_dataframe) 我这样做是因为spark将数据帧写入hdfs非常容易: dataframe.write.parquet(output_uri, mode="overwrite", compression="snappy")

我和熊猫以及spark数据帧一起工作。数据帧总是非常大(>20GB),标准spark函数不足以满足这些大小。目前,我正在将我的pandas数据帧转换为spark数据帧,如下所示:

dataframe = spark.createDataFrame(pandas_dataframe)  
我这样做是因为spark将数据帧写入hdfs非常容易:

dataframe.write.parquet(output_uri, mode="overwrite", compression="snappy")
但是对于大于2GB的数据帧,转换失败了。 如果我将spark数据帧转换为熊猫,我可以使用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的快速对话,它也适用于大于2GB的数据帧。但我却找不到另一种方法。这意味着有一个熊猫数据帧,我在pyarrow的帮助下将其转换为spark。问题是我真的找不到如何将熊猫数据帧写入hdfs

我的熊猫版本:0.19.0

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

问题解决了

将数据帧转换为R对象

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


因此,也许转换pandas->R->Spark->hdfs?

一个技巧可能是从大的pandas创建N个pandas数据帧(每个小于2GB)(水平分区),并创建N个不同的Spark数据帧,然后合并(联合)它们以创建最后一个写入hdfs。我假设您的主计算机功能强大,但您也有一个运行Spark的集群

这意味着有一个熊猫数据帧,我在pyarrow的帮助下将其转换为spark

您想要的功能是:

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

import pyarrow.parquet as pq

fs  = pa.hdfs.connect()

with fs.open(path, "wb") as fw
    pq.write_table(adf, fw)
另请参见

  • 在公园里
火花注释

此外,由于Spark 2.3(当前主控)箭头在
createDataFrame
()中直接受支持。这样您就可以轻松控制各个批次的大小

最后,
defaultParallelism
可以用来控制使用标准的
\u convert\u from\u pandas
生成的分区数量,有效地将切片的大小减少到更易于管理的程度

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


实际上,只要使用本地Pandas
DataFrame
作为输入,我看不出有任何理由在这里切换到Spark。此场景中最严重的瓶颈是驱动程序的网络I/O,分发数据无法解决此问题。

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

此处
astype
将列的类型从
object
更改为
string
。这可以避免引发异常,因为spark无法识别熊猫的类型
对象
。但要确保这些列的类型确实是string

现在将df保存在hdfs中:

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

你犯了什么错误?您确定应用程序在写入时失败了吗?或者可能在一点之前(在数据帧转换期间)?由于java堆空间受到限制,并且createDataFrame方法正在java堆上构建字节数组,因此应用程序在内存不足的情况下失败。为了解决这个问题,我们需要pyarrow解决方案。如前所述,它已经非常适合spark to pandas。但是我也需要熊猫来激发我的灵感,因为我找不到一种直接将熊猫保存到hdfs或蜂巢的方法。只是好奇——这么大的熊猫,为什么不直接将数据写入数据库呢?例如,Postgres,如果您仍然想编写Python或C代码来在数据库中对其进行操作。一种方法可能是从大数据帧创建N个pandas数据帧(每个小于2GB)(水平分区),并创建N个不同的spark数据帧,然后合并(联合)它们以创建最后一个数据帧写入HDFS。我假设您的主计算机功能强大,但您也有一个运行Spark的集群。
import pyarrow.parquet as pq

fs  = pa.hdfs.connect()

with fs.open(path, "wb") as fw
    pq.write_table(adf, fw)
    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)

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