对比Pandas,学习PySpark大数据处理

本文转自公众号数据STUDIO

在这篇文章中,我们将对比用于基本数据操作任务的 pandas 代码片段和它们在 PySpark 中的对应功能的代码片段。利用 pandas 数据操作技能来学习 PySpark 。

对于数据分析师、数据科学家和任何使用数据的人来说,能够熟练而有效地处理大数据是一项非常有优势的技能。如果你已经熟悉运用 Python 和 pandas 做常规数据处理,并且想学习处理大数据,那么熟悉 PySpark,并将用其做数据处理,将会是一个不错的开始。PySpark是一种适用于 Apache Spark 的 Python API,一种流行的大数据开源数据处理引擎。

本文的前提是,假设读者在 Python 中熟练使用 pandas 操作数据。

数据集

从导包开始。在 PySpark 中,需要创建一个 Spark 会话 SparkSession。创建 Spark 会话后,可以从以下位置访问 Spark Web 用户界面 (Web UI):http://localhost:4040/。下面定义的应用程序名称appName为“PyDataStudio”,将显示为 Web UI 右上角的应用程序名称。本文将不会使用 Web UI,但是,如果您有兴趣了解更多信息,请查看官方文档[1]

import pandas as pd
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName('PyDataStudio').getOrCreate()
d4f93c4914a920f35be97fe804a37727.png

我们将在这篇文章中使用企鹅数据集[2]。使用下面的脚本,我们将penguins.csv数据的修改版本保存在工作目录中。

from seaborn import load_dataset
(load_dataset('penguins')
    .drop(columns=['bill_length_mm', 'bill_depth_mm'])
    .rename(columns={'flipper_length_mm': 'flipper',
                     'body_mass_g': 'mass'})
    .to_csv('penguins.csv', index=False))
85395ffdaff97adf289e146a5ae4be58.png

看一下两个库之间的语法比较。为了简洁,我们仅保留显示 PySpark 输出。

基本使用

两个库的数据对象都称为 DataFrame:pandas DataFrame vs PySpark DataFrame

导入数据并检查其形状

# pandas 
df = pd.read_csv('penguins.csv') 
df.shape
# PySpark 
df = spark.read.csv('penguins.csv', header=True, inferSchema=True) 
df.count(), len(df.columns)
(344, 5)

使用 PySpark 导入数据时,指定header=True数据类型用第一行作标题,并设置inferSchema=True。可以尝试不使用这些选项导入并检查 DataFrame 及其数据类型(类似于 pandas 使用df.dtype 检查 PySpark DataFrames 的数据类型)。

与 pandas DataFrame 不同,PySpark DataFrame 没有像.shape可以直接查看数据的形状。所以要得到数据形状,我们分别求行数和列数。

检查有关数据的高级信息

# pandas
df.info()
# PySpark 
df.printSchema()
root
 |-- species: string (nullable = true)
 |-- island: string (nullable = true)
 |-- flipper: double (nullable = true)
 |-- mass: double (nullable = true)
 |-- sex: string (nullable = true)

虽然此方法不会提供与df.info()相同的输出,但它是最接近的内置方法之一。

查看数据的前几行

# pandas
df.head()
# PySpark 
df.show(5)
+-------+---------+-------+------+------+
|species|   island|flipper|  mass|   sex|
+-------+---------+-------+------+------+
| Adelie|Torgersen|  181.0|3750.0|  Male|
| Adelie|Torgersen|  186.0|3800.0|Female|
| Adelie|Torgersen|  195.0|3250.0|Female|
| Adelie|Torgersen|   null|  null|  null|
| Adelie|Torgersen|  193.0|3450.0|Female|
+-------+---------+-------+------+------+
only showing top 5 rows

默认情况下,df.show()默认显示前 20 行。PySpark DataFrame 实际上有一个名为.head()的方法,可以查看前几行的数据,并以row对象形式打印出。运行df.head(5)提供如下输出:

df.head(5)
ca22f150c9d9a0c3b132366735888ccb.png

.show()方法的输出更简洁,因此在查看数据集的top行时用.show()

选择列

# pandas 
df[['island', 'mass']].head(3)
# PySpark 
df[['island', 'mass']].show(3)
+---------+------+
|   island|  mass|
+---------+------+
|Torgersen|3750.0|
|Torgersen|3800.0|
|Torgersen|3250.0|
+---------+------+
only showing top 3 rows

虽然可以在这里使用的是类似于 pandas 的语法,而在 PySpark 中默认使用如下代码片段所示的方法选择列:

df.select('island', 'mass').show(3) 
df.select(['island', 'mass']).show(3)

过滤

根据条件过滤数据

# pandas 
df[df['species']=='Gentoo'].head()
# PySpark 
df[df['species']=='Gentoo'].show(5)
+-------+------+-------+------+------+
|species|island|flipper|  mass|   sex|
+-------+------+-------+------+------+
| Gentoo|Biscoe|  211.0|4500.0|Female|
| Gentoo|Biscoe|  230.0|5700.0|  Male|
| Gentoo|Biscoe|  210.0|4450.0|Female|
| Gentoo|Biscoe|  218.0|5700.0|  Male|
| Gentoo|Biscoe|  215.0|5400.0|  Male|
+-------+------+-------+------+------+
only showing top 5 rows

两个库之间的语法几乎相同。要获得相同的输出,还可以使用:

df.filter(df['species']=='Gentoo').show(5) df.filter("species=='Gentoo'").show(5)

下面显示了一些常见的过滤器比较:

# pandas 
df[df['species'].isin(['Chinstrap', 'Gentoo'])].head() 
df[df['species'].str.match('G.')] .head() 
df[df['flipper'].between(225,229)].head() 
df[df['mass'].isnull()].head()1b df.loc[df['species']!='Gentoo'].head() 
df[~df['species'].isin(['Chinstrap', 'Gentoo'])].head() 
df[-df['species'].str.match('G.')].head() 
df[~df['flipper'].between(225,229)].head() 
df[df['mass'].notnull()].head()6 df[(df['mass']<3400) & (df['sex']=='Male')].head() 
df[(df['mass']<3400) | (df['sex']=='Male')].head()

# PySpark 
df[df['species'].isin(['Chinstrap', 'Gentoo'])].show(5) 
df[df['species'].rlike('G.')].show(5) 
df[df['flipper'].between(225,229)].show(5) 
df[df['mass'].isNull()].show(5)1b df[df['species']!='Gentoo'].show(5) 
df[~df['species'].isin(['Chinstrap', 'Gentoo'])].show(5) 
df[~df['species'].rlike('G.')].show(5) 
df[~df['flipper'].between(225,229)].show(5) 
df[df['mass'].isNotNull()].show(5)
df[(df['mass']<3400) & (df['sex']=='Male')].show(5) 
df[(df['mass']<3400) |(df[ 'sex']=='Male')].show(5)

虽然~-在 pandas 中都可以作为否定,但在 PySpark 中仅有~能作为有效的否定。

排序

对数据进行排序并检查mass最小的 5 行:

# pandas 
df.nsmallest(5, 'mass')
# PySpark 
df[df['mass'].isNotNull()].orderBy('mass').show(5)
+---------+------+-------+------+------+
|  species|island|flipper|  mass|   sex|
+---------+------+-------+------+------+
|Chinstrap| Dream|  192.0|2700.0|Female|
|   Adelie|Biscoe|  184.0|2850.0|Female|
|   Adelie|Biscoe|  181.0|2850.0|Female|
|   Adelie|Biscoe|  187.0|2900.0|Female|
|   Adelie| Dream|  178.0|2900.0|Female|
+---------+------+-------+------+------+
only showing top 5 rows

Pandas的.nsmallest().nlargest()方法会自动排除缺失值。而 PySpark 没有等效的方法。为了获得相同的输出,首先过滤掉缺失mass的行,然后对数据进行排序并查看前 5 行。如果没有删除数据,可以简写为:

df.orderBy(‘mass’).show(5).sort()

代替的另一种排序方式.orderBy()

# pandas 
df.nlargest(5, 'mass')
# PySpark 
df.sort('mass', ascending=False).show(5)
+-------+------+-------+------+----+
|species|island|flipper|  mass| sex|
+-------+------+-------+------+----+
| Gentoo|Biscoe|  221.0|6300.0|Male|
| Gentoo|Biscoe|  230.0|6050.0|Male|
| Gentoo|Biscoe|  220.0|6000.0|Male|
| Gentoo|Biscoe|  222.0|6000.0|Male|
| Gentoo|Biscoe|  229.0|5950.0|Male|
+-------+------+-------+------+----+
only showing top 5 rows

这些语法的变体也是等效的:

df.sort(df['mass'].desc()).show(5) 
df.orderBy('mass', ascending=False).show(5) 
df.orderBy(df['mass'].desc( )).show(5)

按多列排序,如下所示:

# pandas 
df.sort_values(['mass', 'flipper'], ascending=False).head()
# PySpark 
df.orderBy(['mass', 'flipper'], ascending=False).show(5)
+-------+------+-------+------+----+
|species|island|flipper|  mass| sex|
+-------+------+-------+------+----+
| Gentoo|Biscoe|  221.0|6300.0|Male|
| Gentoo|Biscoe|  230.0|6050.0|Male|
| Gentoo|Biscoe|  222.0|6000.0|Male|
| Gentoo|Biscoe|  220.0|6000.0|Male|
| Gentoo|Biscoe|  229.0|5950.0|Male|
+-------+------+-------+------+----+
only showing top 5 rows

在 PySpark 中,可以在将所有列分别传参数,而不需要写成列表的形式

df.orderBy('mass', 'flipper', ascending=False).show(5)

要按多列但按不同方向排序:

# pandas 
df.sort_values(['mass', 'flipper'], ascending=[True, False]).head()
# PySpark 
df[df['mass'].isNotNull()]\ 
  .sort('mass', 'flipper', ascending=[True, False]).show(5)
+---------+---------+-------+------+------+
|  species|   island|flipper|  mass|   sex|
+---------+---------+-------+------+------+
|Chinstrap|    Dream|  192.0|2700.0|Female|
|   Adelie|   Biscoe|  184.0|2850.0|Female|
|   Adelie|   Biscoe|  181.0|2850.0|Female|
|   Adelie|Torgersen|  188.0|2900.0|Female|
|   Adelie|   Biscoe|  187.0|2900.0|Female|
+---------+---------+-------+------+------+
only showing top 5 rows

pyspark的另一种写法

df[df['mass'].isNotNull()]\
  .orderBy(df['mass'].asc(), df['flipper'].desc()).show(5)

0a900c7dcc89726937b81ec6e3473fa1.png

1d822cbb09bfd7d308db045e5578ca29.png

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值