pyspark数据处理之----全量查询select和条件查询filter

在spark中,对数据的查询和数据库是有点对齐的,有条件查询也有部分列查询

头文件导入和测试数据创建

具体如何创建原始dataframe数据,请看上一篇博客(dataframe的8种创建方法

from pyspark.sql import SparkSession
spark = SparkSession.builder.appName('increase delete change select').master('local').getOrCreate()
df = spark.createDataFrame([
    ['alex',1,2,'string1'],
    ['paul',11 ,12,'string2'],
    ['alex',21,22,'leon'],
    ['james',31,32,'traveler']],schema=('name string,a long, b long, c string'))
df.show()
+-----+---+---+--------+
| name|  a|  b|       c|
+-----+---+---+--------+
| alex|  1|  2| string1|
| paul| 11| 12| string2|
| alex| 21| 22|    leon|
|james| 31| 32|traveler|
+-----+---+---+--------+

条件查询

  对数据的条件查询其实是针对具体的 进行操作的,所以可以认为每一次的条件查询,都是要把条件施加到具体的某一上,比如 df.filter(df.age > 10), 这个大于10的条件筛选其实就是施加在具体的age列上的。

条件查询用filter,具体的格式如下:

  • df [‘筛选条件’]
  • df.filter (‘筛选条件’)
  • df.where (‘筛选条件’)

  filter和where二者的用法一样,所以二选一讲解即可

1.区间查询

这是我自己命名的的,我认为大于或者小于某个数都是在一个区间范围内,无外乎这个区间是有限还是无限。

1.1. 在区间查询上,通常最常规的当然是利用关系运算符进行查询(> , < , == )
下图是筛选所有记录中,a列中大于20的数据记录。

分别用两种格式来演示

#这是利用关系运算符进行查询的,< 和 ==的查询类似
df.filter(df.a > 20).show()
+-----+---+---+--------+
| name|  a|  b|       c|
+-----+---+---+--------+
| alex| 21| 22|    leon|
|james| 31| 32|traveler|
+-----+---+---+--------+
df[df.a > 20].show()
+-----+---+---+--------+
| name|  a|  b|       c|
+-----+---+---+--------+
| alex| 21| 22|    leon|
|james| 31| 32|traveler|
+-----+---+---+--------+

1.2,between(lowerBound, upperBound)
查询最低值lowerBound到最高值upperBound之间的数据记录
下图是筛选所有记录中,a列中数据在10-30之间的数据记录

df.filter(df.a.between(10,30)).show()
+----+---+---+-------+
|name|  a|  b|      c|
+----+---+---+-------+
|paul| 11| 12|string2|
|alex| 21| 22|   leon|
+----+---+---+-------+

2.字符串的子串的包含查询

2.1 contains(other)
  查询某一列中包含子串other的数据记录,通常这个other是一个字符串
  下图是筛选所有记录中,c列值包含str的数据记录
  值得注意的是:这个作为一个字串,在实际的查询的字符串中,它可以是任何位置,比如有一个值是string1,这里contains的参数other如果是in,那他会在string1中每一个位置搜寻in,找到即可。

df.filter(df.c.contains('str')).show()
+----+---+---+-------+
|name|  a|  b|      c|
+----+---+---+-------+
|alex|  1|  2|string1|
|paul| 11| 12|string2|
+----+---+---+-------+

2.2 like(str)
  查询满足str条件的数据,通常这个str是一个由字符串和通配符组成的
  下图是筛选所有记录中,c列值以on结尾的数据记录
  值得注意是:这个on的位置是固定,必须是在尾部,因为前面有一个on的通配符,如果是on%,那on必须在开头,所以这个on的位置是由我们自己设定的,这点是和contains不同之处;当然如果你想在任何位置找on,则可以是%on%,关于通配符的一些使用,可以自行百度。

df.filter(df.c.like('%on')).show()
+----+---+---+----+
|name|  a|  b|   c|
+----+---+---+----+
|alex| 21| 22|leon|
+----+---+---+----+

2.3 startswith(other)
  查询数据是以other开头的数据记录
  下图是筛选所有记录中,c列值以str开头的数据记录
  注意:这里其实好比是contains和like的特殊形式

df.filter(df.c.startswith('str')).show()
+----+---+---+-------+
|name|  a|  b|      c|
+----+---+---+-------+
|alex|  1|  2|string1|
|paul| 11| 12|string2|
+----+---+---+-------+

2.4 endswith(other)
  查询数据是以other结尾的数据记录
  下图是筛选所有记录中,c列值以ing2结尾的数据记录
  注意:这里其实好比是contains和like的特殊形式

df.filter(df.c.endswith('ing2')).show()
+----+---+---+-------+
|name|  a|  b|      c|
+----+---+---+-------+
|paul| 11| 12|string2|
+----+---+---+-------+

2.5.isin(*cols)
  查询具体列中,包含在cols下的数据,通常这可以叫具体查询
  下图是筛选所有记录中,c列值为string1和Leon的数据记录

df.filter(df.c.isin(['string1','leon'])).show()
+----+---+---+-------+
|name|  a|  b|      c|
+----+---+---+-------+
|alex|  1|  2|string1|
|alex| 21| 22|   leon|
+----+---+---+-------+

3.空值查询

3.1.isNotNull()
  列中非空值筛选
  下图是筛选所有记录中,a不为0的数据记录。

df.filter(df.a.isNotNull()).show()
+-----+---+---+--------+
| name|  a|  b|       c|
+-----+---+---+--------+
| alex|  1|  2| string1|
| paul| 11| 12| string2|
| alex| 21| 22|    leon|
|james| 31| 32|traveler|
+-----+---+---+--------+

3.2.isNull()
  列中空值筛选
  下图是筛选所有记录中,a为0的数据记录。

df.filter(df.a.isNull()).show()
+----+---+---+---+
|name|  a|  b|  c|
+----+---+---+---+
+----+---+---+---+

部分列查询

具体格式如下:

  • df.select(要显示的列)
  • df[要显示的列]

由于这俩的效果是完全一样的,

1.select部分列查询

关于select怎么查,其实就是把想要的列往里丢就行,所以这里就讲解一下,这个往里丢丢列名该怎么写

1.1第一种查询,用’.'来表示列
  下图是查询a列和c列

df.select(df.a,df.c).show()
+---+--------+
|  a|       c|
+---+--------+
|  1| string1|
| 11| string2|
| 21|    leon|
| 31|traveler|
+---+--------+

1.2.第二种查询,用[]来表示列
  下图是查询a列和c列

df.select(df['a'],df['c']).show()
+---+--------+
|  a|       c|
+---+--------+
|  1| string1|
| 11| string2|
| 21|    leon|
| 31|traveler|
+---+--------+

1.2.第三种查询,用pyspark中的function中的col来制定列
  下图是查询a列和c列

from pyspark.sql import functions as F
df[F.col('a'),F.col('c')].show()
+---+--------+
|  a|       c|
+---+--------+
|  1| string1|
| 11| string2|
| 21|    leon|
| 31|traveler|
+---+--------+

2.[ ]部分列查询

同样的,对于这样的方式,你可以有三种写法:
第一种就是利用’.'来访问列,比如:df [ df.a,df.c ]
第二种就是利用[]来访问列,比如:df [ df[‘a’] , df[‘c’] ]
第三种就是利用名字来访问列,比如:df [ ‘a’,‘c’ ]
第三种就是利用col来访问列,比如:df [ F.col(‘a’),F.col(‘c’) ]
下图是查询a列和c列的部分演示

df[[df.a,df.c]].show()
+---+--------+
|  a|       c|
+---+--------+
|  1| string1|
| 11| string2|
| 21|    leon|
| 31|traveler|
+---+--------+
#3.全量查询的第三种表达
df['a','c'].show()
+---+--------+
|  a|       c|
+---+--------+
|  1| string1|
| 11| string2|
| 21|    leon|
| 31|traveler|
+---+--------+

3.部分列查询+条件筛选

  全量查询也可以加筛选条件,但是和条件查询的差异在于,它不会将不符合条件的值筛选掉,而是会将施加筛选条件的那一列二值化,不符合条件的为false,符合条件的为true

df.select(df.a,df.b> 20 ).show()
+---+--------+
|  a|(b > 20)|
+---+--------+
|  1|   false|
| 11|   false|
| 21|    true|
| 31|    true|
+---+--------+

  这里插入一点和查询无关的知识点(列名修改和类型转化),因为从上面的查询结果看出,经过筛选之后,我们得到的b列因为施加了筛选条件后,列名改变了,如下图所示:
在这里插入图片描述
  但是有时候我们并不想改变名字,活着想改一个其他的名字,这时候就需要用到alias关键字,在alias里面写你想要起的列名就行。

df.select(df.a,(df.b> 20).alias('新名字') ).show()
+---+------+
|  a|新名字|
+---+------+
|  1| false|
| 11| false|
| 21|  true|
| 31|  true|
+---+------+

  这时候列名就被我们改变了,如果你想改回原来的列名“b”,依照葫芦画瓢就行。
  但是还有一个问题,可以看一下加工后的列的值,是bool值,但是如果你想改改为0,1的值,这就涉及到一个cast关键字,在cast中写下你想要转化的类型就行啦
下面是进行类型转换后对列名进行了重命名

df.select(df.a,(df.b> 20).cast('int').alias("w")).show()
+---+---+
|  a|  w|
+---+---+
|  1|  0|
| 11|  0|
| 21|  1|
| 31|  1|
+---+---+

全量查询+替换

  接着上面的说,上面的例子可以将符合条件的变为true,不符合的变为false,那具体的应用场景是什么呢?
我们还能做些什么呢?,我们可以进行批量改写,这时候就引出一个when…otherwise()
这个when的api是在functions下,若以需要进行额外的引入

下图是将b列中,大于20的改为888,否则就为999

from pyspark.sql import functions as F
df.select(df.a,F.when(df.b > 20, 888).otherwise(999)).show()
+---+----------------------------------------+
|  a|CASE WHEN (b > 20) THEN 888 ELSE 999 END|
+---+----------------------------------------+
|  1|                                     999|
| 11|                                     999|
| 21|                                     888|
| 31|                                     888|
+---+----------------------------------------+

下图是将b列中,大于20的改为888,小于10的改为666,否则就为999

df.select(df.a,F.when(df.b > 20, 888).when(df.b < 10,666).otherwise(999)).show()
+---+---------------------------------------------------------------+
|  a|CASE WHEN (b > 20) THEN 888 WHEN (b < 10) THEN 666 ELSE 999 END|
+---+---------------------------------------------------------------+
|  1|                                                            666|
| 11|                                                            999|
| 21|                                                            888|
| 31|                                                            888|
+---+---------------------------------------------------------------+

列名重命名

  从以上的几个例子发现施加条件筛选后的列名奇奇怪怪,很长,这显然不是我们想要的,这时候可以对其进行列名的修改,将其改为原来的列名 ,其实在上上小节已经讲过一点点了。

  • .alias(‘列名’)
  • .name(‘列名’)

下面举个例子:
  未改列名之前,列名很长

df.select(df.a,F.when(df.b > 20, 888).when(df.b < 10,666).otherwise(999)).show()
+---+---------------------------------------------------------------+
|  a|CASE WHEN (b > 20) THEN 888 WHEN (b < 10) THEN 666 ELSE 999 END|
+---+---------------------------------------------------------------+
|  1|                                                            666|
| 11|                                                            999|
| 21|                                                            888|
| 31|                                                            888|
+---+---------------------------------------------------------------+

修改列名后

df.select(df.a,F.when(df.b > 20, 888).when(df.b < 10,666).otherwise(999).alias('b')).show()
+---+---+
|  a|  b|
+---+---+
|  1|666|
| 11|999|
| 21|888|
| 31|888|
+---+---+
df.select(df.a,F.when(df.b > 20, 888).when(df.b < 10,666).otherwise(999).name('b')).show()
+---+---+
|  a|  b|
+---+---+
|  1|666|
| 11|999|
| 21|888|
| 31|888|
+---+---+

数据类型修改

有时候想对数据进行类型转换,比如将某一列的bingint型转为string类型这样,可以有两种方法。

  • 一种方法是astype();
  • 一种方法是case();

二者的用法是完全一致的

df
DataFrame[name: string, a: bigint, b: bigint, c: string]
df[df.a,df.b.astype('string'),df.c]
DataFrame[a: bigint, b: string, c: string]
df[df.a.cast('string'),df.b.astype('string'),df.c]
DataFrame[a: string, b: string, c: string]
  • 3
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值