我正在使用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
答案 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)
另见
pyarrow
documentation。
Spark说明:
此外,因为createDataFrame
(SPARK-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的集群。