pandas dataframe 和 pyspark dataframe

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、pandas是什么?
  • 二、使用步骤
    • 1.创建DataFrame
    • 2.选取数据
      • 列选取
      • 行选取
      • 条件选择(根据A列值选择B列)
    • 增加删减
      • 列增加/替换/重命名
      • 删除列
      • 删除行
      • 去重
    • 将函数运用于列和行
      • 将函数运用于列
      • 将函数运用于行
    • 统计
      • 全局
        • 分组
      • 缺失值处理
      • 排序
    • 拼接 concat/union
    • 联结
  • pyspark dataframe 独有的操作
    • 给RDD加递增序列号
    • row_number
    • 将dataframe注册成临时表
    • PySpark DataFrame求差集,交集,并集
  • 总结


前言

提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、pandas是什么?

pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。单机single machine tool,没有并行机制,处理大量数据有瓶颈。
pyspark 是分布式并行计算框架。所有的数据和操作自动并行分布在各个集群节点上。能够处理大量的数据

二、使用步骤

1.创建DataFrame

pandas dataframe:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
############################################# 1. 通过list生成测试数据
pd_df = pd.DataFrame(
{
'name':['Jack','Tom','Alice'],
'age':[20,23,21],
'weight':[150,180,98]
},
index=['a', 'b', 'c']
)
print(pd_df.head())
############################################# 2. 读取本地csv/excel文件
pd.read_csv('data.csv') 
pd.read_excel('data.xlsx', sheet_name = 0)
############################################# 3. 将pyspark df转为pandans df
spark_df.toPandas()

pyspark dataframe:

import requests
import json
import datetime
from pyspark.sql import SparkSession
import pyspark.sql.functions as F
import pandas as pd
import os
import numpy as np
os.environ['PYSPARK_PYTHON']='/usr/local/anaconda3/bin/python3.6'
import datetime
import seaborn as sns
import matplotlib.pyplot as plt
from pyspark.sql.window import *
from pyspark.sql import Window
spark = (SparkSession
 .builder
 .appName("gps-test-DockerLinuxContainer")
 .enableHiveSupport()
 .config("spark.executor.instances", "300")
 .config("spark.executor.memory","8g")
 .config("spark.executor.cores","4")
 .config("spark.driver.memory","4g")
 .config("spark.driver.maxResultSize", "8g")
 .config("spark.sql.shuffle.partitions","1200")
 .config("spark.yarn.appMasterEnv.yarn.nodemanager.container-executor.class","DockerLinuxContainer")
 .config("spark.executorEnv.yarn.nodemanager.container-executor.class","DockerLinuxContainer")
 .config("spark.yarn.appMasterEnv.yarn.nodemanager.docker-container-executor.image-name","bdp-docker.jd.com:5000/wise_mart_bag:latest")
 .config("spark.executorEnv.yarn.nodemanager.docker-container-executor.image-name","bdp-docker.jd.com:5000/wise_mart_bag:latest")
 .config("spark.sql.legacy.allowCreatingManagedTableUsingNonemptyLocation","true")
 .getOrCreate())

SparkSession.createDataFrame()


############################################# 1
sentenceDataFrame = spark.createDataFrame((
      (1, "asf"),
      (2, "2143"),
      (3, "rfds")
    )).toDF("label", "sentence")

############################################# 2:通过list + structType 创建
from pyspark.sql.types import StructType,StructField, StringType, IntegerType
data2 = [("James","","Smith","36636","M",3000),
    ("Michael","Rose","","40288","M",4000),
    ("Robert","","Williams","42114","M",4000),
    ("Maria","Anne","Jones","39192","F",4000),
    ("Jen","Mary","Brown","","F",-1)
  ]
schema = StructType([ \
    StructField("firstname",StringType(),True), \
    StructField("middlename",StringType(),True), \
    StructField("lastname",StringType(),True), \
    StructField("id", StringType(), True), \
    StructField("gender", StringType(), True), \
    StructField("salary", IntegerType(), True) \
  ])
df = spark.createDataFrame(data=data2,schema=schema)
df.printSchema()
df.show(100,truncate=False)

############################################# 3.读取hive表
sql = """ select * from table """
df = SparkSession.sql()
############################################# 4. 从json中读取
df = SparkSession.read.json()
############################################# 3. 由pandas_df转化而来
df = SparkSession.createDataFrame(pandas_df)

2.选取数据

列选取

pandas dataframe:

############################################# 1. 返回Series:
pandas_df['col']
pandas_df.col
############################################# 2. 返回DataFrame:
pandas_df[['col1', 'col2']]
pandas_df["col1":"col2"]

pyspark dataframe:

############################################# 1. 返回Column:
spark_df['col']
############################################# 2. 返回DataFrame:
spark_df.select('col1', 'col2')
spark_df.select(spark_df.a, spark_df.b, spark_df.c)    # 选择a、b、c三列
spark_df.select(spark_df["a"], spark_df["b"], spark_df["c"])    # 选择a、b、c三列
############################################# 3. 选取列并对列进行sql函数应用
spark_df.select(spark_df['name'], spark_df['age']+1)
# selectExpr函数是select的变种,除了select已有的功能,还可以解析sql表达式
spark_df.selectExpr('col1 * 2', 'abs(col2)')
df.selectExpr("colA", "colB as newName", "abs(colC)")
df.select(expr("colA"), expr("colB as newName"), expr("abs(colC)"))

行选取

pandas dataframe:

############################################# 1. 根据位置序号
# 使用切片
pandas_df[:2]
# 选取某一行 
pandas_df.iloc[2]
# 筛选多行多列,根据行序号和列序号
pandas_df.iloc[[0,2], [3,4]]
pandas_df.iloc[0:2, 3:4]



############################################# 2. 根据index
# 通过index 和 col_name进行选择, 多行多列
pandas_df.loc['index_1':'index_2', 'col_1':'col_2']
pandas_df.loc[['index_1','index_2'], ['col_1','col_2']]



############################################# 3. 根据条件筛选行(整行)
pandas_df[pandas_df['age'] >20]
pandas_df1 = pandas_df[(pandas_df['name'].isin(['Jack'])) & (pandas_df['weight'] > 100)]
pandas_df.query(‘age > 20 & age < 22)



############################################# 4. 选取头尾行
pandas_df.head()
pandas_df.tail()

pyspark dataframe:

############################################# 1. 返回第一行
## 注:first()函数返回的是Row类型,可以看成是dict,当只select一列时,可以通过[0]来取到值
value = df.select('columns_name').first()[0]
## first() 返回的是 Row 类型,用 row.col_name 来获取列值
row = df.select('col_1', 'col_2').first()
col_1_value = row.col_1
col_2_value = row.col_2


############################################# 2. 根据条件筛选行(整行)
spark_df.where('age > 20 and age < 22')
spark_df.where('age > '+age_value_min+' and age < '+age_value_max)
## case when 的实现
from pyspark.sql import functions as F
df.select(df.name, F.when(df.age > 4, 1).when(df.age < 3, -1).otherwise(0)).show(100,False)
+-----+------------------------------------------------------------+
| name|CASE WHEN (age > 4) THEN 1 WHEN (age < 3) THEN -1 ELSE 0 END|
+-----+------------------------------------------------------------+
|Alice|                                                          -1|
|  Bob|                                                           1|
+-----+------------------------------------------------------------+


############################################# 3. 选取头部/尾部几行
spark_df.head(10)
spark_df.take(10)

条件选择(根据A列值选择B列)

pandas dataframe:

df = pandas_df.loc[lambda df: df['col_A'] == "string", lambda df: ['col_B']]

pyspark dataframe:

result = table_desc_df.select("col_B").where("col_A = '"+label_need+"'")
## 这样返回的是dataframe的类型: DataFrame[data_type: string]
## 通过collect可以转为array 的类型 result.collect() 返回:[Row(data_type='string')]
## result.collect()[0] 返回:Row(data_type='string')
## result.collect()[0][0]返回:string
综述,取出dataframe中的单元值

result = table_desc_df.where("""col_name = '"""+label_need+"""'""").select("data_type").collect()[0][0]

## 也可以通过rdd操作来实现
table_desc_df.select("col_name","data_type").rdd.map(lambda row: (row[0],row[1]).where("""col_name = '"""+label_need+"""'""").collect()


######### 过滤 null/nan 数据
from pyspark.sql.functions import isnan, isnull
df = df.filter(isnull("a"))  # 把a列里面数据为null的筛选出来(代表python的None类型)
df = df.filter(isnan("a"))  # 把a列里面数据为nan的筛选出来(Not a Number,非数字数据)

增加删减

列增加/替换/重命名

pandas dataframe:

pandas_df['new_col']=1
pandas_df['income'] = [1000,2000,3000]

# 第一个参数指定插入列的位置,第二个参数指定插入列的列名,第三个参数指定插入列的数据
df1.insert(df1.shape[1], 'profession', ['student','student','teacher'])

pyspark dataframe:

from pyspark.sql import functions as F
# 添加简单的常数值列,如果是新列名就是添加列,如果是旧列名就是替换列
spark_df.withColumn('new_col', F.lit(1))
# 根据旧列转化得到新列
train.withColumn('Purchase_new', train.Purchase /2.0)
train.withColumn('Purchase_new', train.Purchase*(maxValue - minValue) + minValue)
# 列的重命名
new_df = df.withColumnRenamed('old_name', 'new_name')

删除列

pandas dataframe:

## 删除单列
pandas_df.drop('col', axis=1)
## 删除多列
pandas_df.drop(['name', 'age'], axis=1)
pandas_df.drop(columns=['name', 'age'])

pyspark dataframe:

## 删除单列
new_df = spark_df.drop('col')

删除行

pandas dataframe:

## 删除满足某种条件的行
df_clear = df.drop(df[df['x']<0.01].index)
# 也可以使用多个条件
# 删除x小于0.01或大于10的
df_clear = df.drop(df[(df['x']<0.01) | (df['x']>10)].index) 

pyspark dataframe:

## 可以通过filter条件保留需要的行(同比于删除不需要的行)
new_df = spark_df.filter('filter_conditions')
## 删除col1或col2中任一一列包含na的行
df = df.dropna(subset=['col_name1', 'col_name2']) 
## 删除全局中含有na的行
new_df = df.dropna()

去重

pandas dataframe:

new_df = pandas_df['income'].drop_duplicates()  

pyspark dataframe:

pyspark_df.select('columns').distinct().show(100,False)
pyspark_df.select('Age','Gender').dropDuplicates().show()

将函数运用于列和行

将函数运用于列

pandas dataframe:

# 首先实现udf函数,然后通过apply方法,把udf函数apply到每一行上
# 实现一个字符转化
type_mapping = {"Int64":"bigint","Float64":"double"}
def f(old_type):
	return type_mapping(old_type)
pandas_df['new_col'] = pandas_df['new_col','new_col2'].apply(f) 

pyspark dataframe:

# udf函数
#自定义函数的重点在于定义返回值类型的数据格式,其数据类型基本都是从from pyspark.sql.types #import * 导入,常用的包括:
#- StructType():结构体
#- StructField():结构体中的元素
#- LongType():长整型
#- StringType():字符串
#- IntegerType():一般整型
#- FloatType():浮点型
from pyspark.sql.functions import udf 
from pyspark.sql.types import StringType
# 编写函数并且注册成udf,注意定义返回值类型的数据格式
def upperCase(str):
    return str.upper()
upperCaseUDF = udf(lambda z:upperCase(z),StringType())   

# 用在dataframe中
df.withColumn("Cureated Name", upperCaseUDF("Name")).show(truncate=False)
# 用在spark sql中
""" Using UDF on SQL """
spark.sql("select Seqno, upperCase(Name) as Name from NAME_TABLE") \
     .show(truncate=False)

将函数运用于行

pandas dataframe:

pandas_df.apply(f, axis=1) 

pyspark dataframe:

spark_df.foreach(f)

统计

全局

pandas dataframe:

pandas_df.sort_values(by='col')
pandas_df.sort_values(by=['col1', 'col2'], ascending=[0, 1])

pyspark dataframe:

## 统计总行数
spark_df.count()
## 统计学描述
spark_df.describe()
## 对某一列进行求和
## 法1
import pyspark.sql.functions as F     
df.agg(F.sum("my_column")).collect()[0][0]
## 法2
df.select('col').groupBy().sum()
## 法3
df.rdd.map(lambda x: (1,x[1])).reduceByKey(lambda x,y: x + y).collect()[0][1]
## 分别对多列用聚合函数
dfagg = df.agg({"name":"count","age":"max"})
dfagg.show()
+-----------+--------+
|count(name)|max(age)|
+-----------+--------+
|          4|      17|
+-----------+--------+

分组

from pyspark.sql import functions as F
## 分组求count
spark_df.groupBy('key').count().orderBy('count',ascending=False)
data.groupBy('field_pred').agg(F.count(F.lit(1)).alias("cnt"))

## 分组求均值
train.groupby('Age').agg({'Purchase': 'mean'}).show()

## 对一个字段分组,对其余列求函数聚合
dfagg = df.groupBy("gender").agg(F.mean("age").alias("mean_age"),
   F.collect_list("name").alias("names"))
dfagg.show()
+------+--------+------------------+
|gender|avg(age)|collect_list(name)|
+------+--------+------------------+
|  null|    16.0|           [RuHua]|
|female|    16.0|       [HanMeiMei]|
|  male|    16.0|   [LiLei, DaChui]|
+------+--------+------------------+


用agg函数整合后GroupedData类型可用的方法(均返回DataFrame类型):
avg(*cols)     ——   计算每组中一列或多列的平均值
count(F.lit(1))          ——   计算每组中一共有多少行,返回DataFrame有2列,一列为分组的组名,另一列为行总数
max(*cols)    ——   计算每组中一列或多列的最大值
mean(*cols)  ——  计算每组中一列或多列的平均值
min(*cols)     ——  计算每组中一列或多列的最小值
sum(*cols)    ——   计算每组中一列或多列的总和

缺失值处理

pandas dataframe:

# 检测缺失值
Series.isnull()
# 过滤缺失值,默认滤除所有含有缺失值的行
pandas_df.dropna()
# 填充缺失值
# 将所有缺失值填充为value
pandas_df.fillna(value)
# 可以传入一个字典,实现对不同的列填充不同的值,fillna()默认返回新对象,可以设置inplace参数
pandas_df.fillna({1: 0.5, 3: -1})

pyspark dataframe:

# 检测某列是否有缺失值
spark_df.select(F.isnull('col1').alias('r1'))

# 1.删除有缺失值的行
clean_data=final_data.na.drop()
clean_data.show(100, False)

# 2.用均值替换缺失值
import math
from pyspark.sql import functions as F  # 导入spark内置函数
# 计算缺失值,collect()函数将数据返回到driver端,为Row对象,[0]可以获取Row的值
mean_salary = final_data.select(F.mean('salary')).collect()[0][0]
clean_data = final_data.na.fill({'salary':mean_salary})

# 3.如果一行至少2个缺失值才删除该行
final_data.na.drop(thresh=2).show()

# 4.填充缺失值
# 对所有列用同一个值填充缺失值
df1.na.fill('unknown').show()

# 5.不同的列用不同的值填充
df1.na.fill({'LastName':'--', 'Dob':'unknown'}).show()

排序

pandas dataframe:

pandas_df.sort_values(by='col')
pandas_df.sort_values(by=['col1', 'col2'], ascending=[0, 1])

pyspark dataframe:

## 求count
spark_df.orderBy('col')
spark_df.orderBy(['col1', 'col2'], ascending=[0, 1])
## 降序排列
dfsorted = df.sort(df["age"].desc())
dfordered = df.orderBy(df["age"].desc(),df["gender"].desc())

拼接 concat/union

pandas dataframe:

## 左右拼接 (pandas_df1在左 pandas_df2在右)
pd.concat([pandas_df1, pandas_df2])
## 上下拼接
pandas_df1.append(pandas_df2, ignore_index=True)

pyspark dataframe:

## 上下拼接
spark_df1.union(spark_df2)

联结

pandas dataframe:

pd.merge(left, right, how='left', on="key")

pyspark dataframe:

spark_df1.join(spark_df2, ‘name’),默认how=’inner’,联结条件可以是字符串或者Column表达式(列表),如果是字符串,则两边的df必须有该列。使用字符串会合并联结列,使用Column表达式不会合并联结列。常常搭配select()使用。

## 单字段Join
## 合并2个表的join方法:
df_join = df_left.join(df_right, df_left.key == df_right.key, "inner")
# 其中,方法可以为:inner, outer, left_outer, right_outer, leftsemi. 其中注意,一般需要改为:left_outer

## 多字段join
final_data = prediction.join(truth, on=['field_id','dt','model_id'], how='left')

## 混合字段
joinDF1.join(joinDF2 , joinDF1("id" ) === joinDF2( "t1_id"))
dfjoin = df.join(dfmark,(df["name"] == dfmark["name"]) & (df["gender"]==dfmark["sex"]),
        "inner")

pyspark dataframe 独有的操作

给RDD加递增序列号

#将RDD和一个从0开始的递增序列按照拉链方式连接。
rdd_name =  sc.parallelize(["LiLei","Hanmeimei","Lily","Lucy","Ann","Dachui","RuHua"])
rdd_index = rdd_name.zipWithIndex()
print(rdd_index.collect())
# [('LiLei', 0), ('Hanmeimei', 1), ('Lily', 2), ('Lucy', 3), ('Ann', 4), ('Dachui', 5), ('RuHua', 6)]

row_number

# 在某个分组内进行排序,或者给df以某种形式加index (DataFrame)
df = spark.createDataFrame([("LiLei",78,"class1"),("HanMeiMei",87,"class1"),
                           ("DaChui",65,"class2"),("RuHua",55,"class2")]) \
    .toDF("name","score","class")

df.show()
dforder = df.selectExpr("name","score","class",
         "row_number() over (partition by class order by score desc) as order")

dforder.show()
# +---------+-----+------+-----+
# |     name|score| class|order|
# +---------+-----+------+-----+
# |   DaChui|   65|class2|    1|
# |    RuHua|   55|class2|    2|
# |HanMeiMei|   87|class1|    1|
# |    LiLei|   78|class1|    2|
# +---------+-----+------+-----+

spark_df.withColumn(‘row_number’, F.row_number().over(Window.partitionBy(['col1', 'col2']).orderBy(F.desc('col3'))))

将dataframe注册成临时表

df.createTempView("people") 
df2 = spark_session.sql("insert overwrite table partition (dt = '2021-06-18') select * from people")

PySpark DataFrame求差集,交集,并集

# 差集    subtract
newDF = df1.select("sentence").subtract(df2.select("sentence"))
# 交集   intersect
newDF_intersect = df1.select("sentence").intersect(df2.select("sentence"))
# 并集  union
newDF_union = df1.select("sentence").union(df2.select("sentence"))

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

你可能感兴趣的:(python,python)