Spark中DataFrame与Pandas中DataFrame的区别

目录

为何使用 PySpark DataFrame

Pandas DataFrame 数据结构特性

Spark DataFrame 数据结构与存储特性

使用 Spark DataFrame 优势

Spark toPandas 详解

Spark与Pandas中的DataFrame的区别


为何使用 PySpark DataFrame

使用 pandas 进行数据处理,dataframe 常作为主力军出现。基于单机操作的 pandas dataframe 是一种表格形数据结构,拥有丰富、灵活、操作简单的 api,在数据量不大的情况下有较好的效果。

对于大数据量的运算,分布式计算能突破 pandas 的瓶颈,而 Spark 则是分布式计算的典型代表。 Spark 中有三类数据 api,RDD、DataFrame 和 Datasets(支持多种主流语言操作),在 spark2.0 中出现 Datasets 的概念,其中 DataFrame 也称 Datasets[row],python 中只有 DataFrame 的概念。

DataFrame 是基于 RDD 的一种数据类型,具有比 RDD 节省空间和更高运算效率的优点,对于使用 python 操作 spark 且熟悉 pandas 基本操作的工作者是一个好消息。

Pandas DataFrame 数据结构特性

DataFrame 是一种表格型数据结构,按照列结构存储,它含有一组有序的列,每列可以是不同的值,但每一列只能有一种数据类型。DataFrame 既有行索引,也有列索引,它可以看作是由 Series 组成的字典,不过这些 Series 公用一个索引(可以参考下图的数据结构轴线图)。

 


依赖 python 这一简洁明了的语言,dataframe 操作比较简洁,此外 dataframe 还拥有比较丰富的操作 api 接口,能比较容易实现中小型数据集的操作。

Spark DataFrame 数据结构与存储特性

在 Spark 中, DataFrame 是基于 RDD 实现的,一个以命名列方式组织的分布式数据集。实际存储与 RDD 一致,基于行存储,但是 Spark 框架本身不了解 RDD 数据的内部结构,而 DataFrame 却提供了详细的结构信息 (Schema),Spark DataFrame 将数据以单独表结构,分散在分布式集群的各台机器上,所以 spark dataframe 是天然的分布式表结构,具体差异可以参考下图。

 

使用 Spark DataFrame 优势

DataFrame 基于 RDD 的抽象,由于 DataFrame 具有定义好的结构, Spark 可以在作业运行时应用许多性能增强的方法。spark 对于 DataFrame 在执行时间和内存使用上相对于 RDD 有极大的优化。Catalyst 优化引擎使执行时间减少 75%, Project Tungsten Off-heap 内存管理使内存使用量减少 75 +%,无垃圾回收器。使用 DataFrame 比普通 Python RDD(下图中 Python API)实现的快 4 倍,比 Scala RDD(下图中 Scala API)实现快 2 倍。经过 Catalyst 优化后的代码比解释型代码明显快很多。下图给出了 DataFrame 执行速度和空间上的优势。

 


虽说 Spark DataFrame 与 SparkSql 本质上都是实现 sql 的操作,但是 DataFrame 操作不需要像 SparkSql 操作过程中多建一些临时表,且运行性能相对较优(如下图所示),从 Spark 1.3.0 版本开始重点发展 DataFrame;DataFrame 超低的大数据开发入门门槛,完美的避免了不太熟悉的函数式编程,相应地面向对象的编程方式(参考以下自定义基于 DataFrame 的 top K 实现)更符合时代的潮流。

 

 

Spark toPandas 详解

Spark DataFrame 与 Pandas DataFrame 结构形式是如此相似,肯定会有使用者思考是否有 API 能实现二者之间的互相转换。pandas to spark 自不用说,而 spark to pandas 可以通过 toPandas 这一 api 实现。toPandas 等效对 rdd 先做 collect 然后 to dataframe,是将分布式文件收集导本地的操作,转换后的文件能与 pandas 一样实现所有操作。使用 spark 的本意是对海量数据的操作,而转换导本地的 pandas 操作失去了与其本意相差甚远,所以除非必须单机操作,不建议使用该 api。

Spark与Pandas中的DataFrame的区别

  Pandas Spark
工作方式 单机 single machine tool,没有并行机制 parallelism
不支持 Hadoop,处理大量数据有瓶颈
分布式并行计算框架,内建并行机制 parallelism,所有的数据和操作自动并行分布在各个集群结点上。以处理 in-memory 数据的方式处理 distributed 数据。
支持 Hadoop,能处理大量数据
延迟机制 not lazy-evaluated lazy-evaluated
内存缓存 单机缓存 persist() or cache() 将转换的 RDDs 保存在内存
DataFrame 可变性 Pandas 中 DataFrame 是可变的 Spark 中 RDDs 是不可变的,因此 DataFrame 也是不可变的
创建 从 spark_df 转换:pandas_df = spark_df.toPandas() 从 pandas_df 转换:spark_df = SQLContext.createDataFrame(pandas_df)
另外,createDataFrame 支持从 list 转换 spark_df,其中 list 元素可以为 tuple,dict,rdd
list,dict,ndarray 转换 已有的 RDDs 转换
CSV 数据集读取 结构化数据文件读取
HDF5 读取 JSON 数据集读取
EXCEL 读取 Hive 表读取
  外部数据库读取
index 索引 自动创建 没有 index 索引,若需要需要额外创建该列
行结构 Series 结构,属于 Pandas DataFrame 结构 Row 结构,属于 Spark DataFrame 结构
列结构 Series 结构,属于 Pandas DataFrame 结构 Column 结构,属于 Spark DataFrame 结构,如:DataFrame[name: string]
列名称 不允许重名 允许重名
修改列名采用 alias 方法
列添加 df[“xx”] = 0 df.withColumn(“xx”, 0).show() 会报错
from pyspark.sql import functions
df.withColumn(“xx”, functions.lit(0)).show()
列修改 原来有 df[“xx”] 列,df[“xx”] = 1 原来有 df[“xx”] 列,df.withColumn(“xx”, 1).show()
显示   df 不输出具体内容,输出具体内容用 show 方法
输出形式:DataFrame[age: bigint, name: string]
df 输出具体内容 df.show() 输出具体内容
没有树结构输出形式 以树的形式打印概要:df.printSchema()
  df.collect()
排序 df.sort_index() 按轴进行排序  
df.sort() 在列中按值进行排序 df.sort() 在列中按值进行排序
选择或切片 df.name 输出具体内容 df[] 不输出具体内容,输出具体内容用 show 方法
df[“name”] 不输出具体内容,输出具体内容用 show 方法
df[] 输出具体内容,
df[“name”] 输出具体内容
df.select() 选择一列或多列
df.select(“name”)
切片 df.select(df[‘name’], df[‘age’]+1)
df[0]
df.ix[0]
df.first()
df.head(2) df.head(2) 或者 df.take(2)
df.tail(2)  
切片 df.ix[:3] 或者 df.ix[:”xx”] 或者 df[:”xx”]  
df.loc[] 通过标签进行选择  
df.iloc[] 通过位置进行选择  
过滤 df[df[‘age’]>21] df.filter(df[‘age’]>21) 或者 df.where(df[‘age’]>21)
整合 df.groupby(“age”)
df.groupby(“A”).avg(“B”)
df.groupBy(“age”)
df.groupBy(“A”).avg(“B”).show() 应用单个函数
from pyspark.sql import functions
df.groupBy(“A”).agg(functions.avg(“B”), functions.min(“B”), functions.max(“B”)).show() 应用多个函数
统计 df.count() 输出每一列的非空行数 df.count() 输出总行数
df.describe() 描述某些列的 count, mean, std, min, 25%, 50%, 75%, max df.describe() 描述某些列的 count, mean, stddev, min, max
合并 Pandas 下有 concat 方法,支持轴向合并  
Pandas 下有 merge 方法,支持多列合并
同名列自动添加后缀,对应键仅保留一份副本
Spark 下有 join 方法即 df.join()
同名列不自动添加后缀,只有键值完全匹配才保留一份副本
df.join() 支持多列合并  
df.append() 支持多行合并  
缺失数据处理 对缺失数据自动添加 NaNs 不自动添加 NaNs,且不抛出错误
fillna 函数:df.fillna() fillna 函数:df.na.fill()
dropna 函数:df.dropna() dropna 函数:df.na.drop()
SQL 语句 import sqlite3
pd.read_sql(“SELECT name, age FROM people WHERE age>= 13 AND age <= 19″)
表格注册:把 DataFrame 结构注册成 SQL 语句使用类型
df.registerTempTable(“people”) 或者 sqlContext.registerDataFrameAsTable(df, “people”)
sqlContext.sql(“SELECT name, age FROM people WHERE age>= 13 AND age <= 19″)
功能注册:把函数注册成 SQL 语句使用类型
sqlContext.registerFunction(“stringLengthString”, lambda x: len(x))
sqlContext.sql(“SELECT stringLengthString(‘test’)”)
两者互相转换 pandas_df = spark_df.toPandas() spark_df = sqlContext.createDataFrame(pandas_df)
函数应用 df.apply(f)将 df 的每一列应用函数 f df.foreach(f) 或者 df.rdd.foreach(f) 将 df 的每一列应用函数 f
df.foreachPartition(f) 或者 df.rdd.foreachPartition(f) 将 df 的每一块应用函数 f
map-reduce 操作 map(func, list),reduce(func, list) 返回类型 seq df.map(func),df.reduce(func) 返回类型 seqRDDs
diff 操作 有 diff 操作,处理时间序列数据(Pandas 会对比当前行与上一行) 没有 diff 操作(Spark 的上下行是相互独立,分布式存储的)

你可能感兴趣的:(Pandas,PySpark,Pyspark,pandas,dataframe)