Python 随着pyspark数据帧变小,toPandas()是否会加快速度?
我想我会问这个问题。我发现了一种聪明的方法来减小PySpark数据帧的大小并将其转换为Pandas,我只是想知道,随着PySpark数据帧的大小变小,toPandas函数是否会变得更快?下面是一些代码:Python 随着pyspark数据帧变小,toPandas()是否会加快速度?,python,pandas,pyspark,Python,Pandas,Pyspark,我想我会问这个问题。我发现了一种聪明的方法来减小PySpark数据帧的大小并将其转换为Pandas,我只是想知道,随着PySpark数据帧的大小变小,toPandas函数是否会变得更快?下面是一些代码: window = Window.partitionBy(F.lit('A')).orderBy(F.lit('A')) eps_tfs = {} while True: pdf = toPandas(conn.select(F.col('*')).where(F.col('row_nu
window = Window.partitionBy(F.lit('A')).orderBy(F.lit('A'))
eps_tfs = {}
while True:
pdf = toPandas(conn.select(F.col('*')).where(F.col('row_number') <= 2500))
n = len(pdf)
trigger = 0
for u in pdf['features']:
indices = [i for i, x in enumerate(u) if x == 1.0]
for idx in range(len(eps_columns)):
if idx in indices:
try:
eps_tfs[eps_columns[idx]].append(True)
except:
eps_tfs[eps_columns[idx]] = [True]
else:
try:
eps_tfs[eps_columns[idx]].append(False)
except:
eps_tfs[eps_columns[idx]] = [False]
full_view = full_view.append(pd.concat([pdf, pd.DataFrame(eps_tfs)], axis=1))
conn = conn.select(F.col('*')).where(F.col('row_number') > 2500)
conn = conn.drop("row_number")
conn = conn.select(F.col('*'), F.row_number().over(window).alias('row_number'))
eps_tfs = {}
del pdf
if n < 2500:
break
有没有更好的方法来实现这一点?是ToPandas的源代码
首先,是的,如果pyspark数据帧变小,toPandas会更快,它的味道与sdf.collect相似
区别在于ToPandas返回pdf和collect返回列表。
从源代码pdf=pd.DataFrame.from_recordsself.collect中可以看到,columns=self.columns pdf是从列表中的pd.DataFrame.from_记录生成的
因此,如果您的sdf较小,则需要通过网络传输的数据较小,并且可以使用驱动程序的CPU记录较少的数据
第二个代码的设计是不同的,sdf是分布式的,代码调用Mappartition,因此所有工作人员从数据子集生成一个Pandas数据帧,然后调用collect,现在通过网络传输的所有Pandas数据帧被带到驱动程序。然后,代码调用pd.concat将所有数据帧连接在一起
好处是:
在转换为Pandas DataFrame时,所有工作人员并行处理一小部分数据,这比将所有数据带到驱动程序并烧掉驱动程序的CPU以将大数据转换为Pandas要好得多。
正在进行重新分区,这意味着如果您的数据集很大,并且您的分区数很低,则每个分区上的数据都会很大,并且toPandas在序列化程序的OOM上会失败,并且收集数据的速度也非常慢
缺点是:
现在,当您收集时,您并不是在收集本机sdf数据,而是一个附加了更多元数据且通常更大的数据帧,这意味着对象的总大小更大
pd.concat是慢lol,但可能仍然比从_记录更好
因此,没有普遍的结论说哪种方法更好,而是明智地选择使用哪种工具。就像在这个问题中一样,toPandas可能比小型sdf更快,但对于大型sdf,代码片段肯定工作得更好。我会在这里提出不同的问题-pandas是否比pyspark更适合您的用例?如果是,为什么不在pandas中执行所有操作?如果不是,为什么转换?我认为toPandas的源代码应该是:
def _map_to_pandas(rdds):
""" Needs to be here due to pickling issues """
return [pd.DataFrame(list(rdds))]
def toPandas(df, n_partitions=None):
"""
Returns the contents of `df` as a local `pandas.DataFrame` in a speedy fashion. The DataFrame is
repartitioned if `n_partitions` is passed.
:param df: pyspark.sql.DataFrame
:param n_partitions: int or None
:return: pandas.DataFrame
"""
if n_partitions is not None: df = df.repartition(n_partitions)
df_pand = df.rdd.mapPartitions(_map_to_pandas).collect()
df_pand = pd.concat(df_pand)
df_pand.columns = df.columns
return df_pand