我们都知道spark.read读出来的数据格式为pyspark.sql.dataframe.DataFrame,但是pyspark.sql中针对行row&column有特别的数据结构,我很好奇二者是什么关系,如何进行相互转化,于是有了下面这个实验。
from pyspark.sql.functions import *
from pyspark.sql.types import *
from pyspark.sql import SparkSession
from math import log
filePath = './data/Hotel Reservations.csv/'
data = spark.read.csv(filePath, header=True, inferSchema=True)
此时的data的type是 pyspark.sql.dataframe.DataFrame,想要获取行或者列直接slice是行不通的,所以才有如下的一些获取手段。
1. 如何获取数据的行
故事还要从我想将dataframe切片讲起,pyspark内置了head,take,tail等函数,按理说应该能满足你不同程度的需求了,但实际使用起来发现一言难尽。
1.1 基础操作
- 取前k行
data.limit(k)
这个还是没什么问题的,取前k行,重新构成了一个新的dataframe,去验证它的type时还是pyspark.sql.dataframe.DataFrame。
data.take(k)
同样取前k,但返回一个list,就是自动帮你多了一个collect。
- 取后k个
data.tail(n-a)
这个就没那么幸运了,只能返回一个collect后的结果。或者也有limit对应的函数,只是我学识浅薄,暂时不知道。
1.2 Row
那pyspark.sql.types.Row这玩意又是什么呢?没错,就是list中存放的元素。比如说我
a = data.take(k)
a[0]的类型就是types.Row,不如说此刻的我们才成功从dataframe中拿出来某一行了。如果我们想把列再放回去也是非常简单:
df = spark.createDataFrame([row1,row2,...])
2. 如何获取数据的列
既然我们说清楚了行,列其实就应该差不多了吧?确实,不过列其实更灵活一些,因为列都有名字,可以按照key选取自由选取自己想要的^^
data.select(['column1','column2',...])