• spark知识点


      来自官网DataFrames、DataSets、SQL,即sparkSQL模块。

      spark2.0之前,主要的数据格式是RDD(弹性分布式数据集)。spark2.0之后,使用Dataset代替RDD;再,Datasets在Python中是Datasets[Row],故称之为DataFrame,与Python保持一致。

      Dataset API只适用于Scala和Java,使用列名来组织Dataset就是DataFrame,类似于关系型数据库中的表或者Python中的dataframe,且在后台拥有更丰富的优化机制;DataFrame API适用于Scala、Java、Python、R。

      Spark SQL初识:

      初始化一个sparkSession,这是spark中所有功能的切入点

    from pyspark.sql import SparkSession
    
    spark = SparkSession 
        .builder   #builder这里无括号
        .master("local")   #要连接的主机名
       .appName("Python Spark SQL basic example") #CappName只是显示在spark web 中,与本程序名并无关联 .config("spark.some.config.option", "some-value") #对于一个(key,value)对,忽略参数名 .getOrCreate() #如果已有SparkSession则get,否则Create

       

      spark.select用于筛选特定的行,spark.sql用于数据库查询。还可以groupby分组、filter过滤。

      方法调用:

      1)join,同SQL的联合查询,1个表来调用join,参数是另一个表、相等的字段、连接的方式(inner、outer)

      

    people = sqlContext.read.parquet("...")  #两个表,people和department
    department = sqlContext.read.parquet("...")
    
    people.filter(people.age > 30).join(department, people.deptId == department.id)   #连接的字段,倒是比SQL简洁不少
      .groupBy(department.name, "gender").agg({"salary": "avg", "age": "max"})      #groupby分组,分组之后要设置聚合的字段和方式,agg也可单独使用

      2)类 Row :可直接定义一个row同时赋值,也可先声明列名再赋值

    >>> row = Row(name="Alice", age=11)
    >>> row
    Row(age=11, name='Alice')
    >>> row['name'], row['age'] #类似字典
    ('Alice', 11)
    >>> row.name, row.age  #类似属性,dataframe取某一列也是这两种方式
    ('Alice', 11)
    >>> 'name' in row
    True
    >>> 'wrong_key' in row
    False
    
    >>> Person = Row("name", "age")  #先声明,其后再赋值
    >>> Person
    <Row(name, age)>
    >>> 'name' in Person
    True
    >>> 'wrong_key' in Person
    False
    >>> Person("Alice", 11)
    Row(name='Alice', age=11)

      3)利用反射来推测数据模式(数据类型):

    from pyspark.sql import Row  #sql是个模块,而Row是个类,故不能直接 import pyspark.sql.Row
    
    sc = spark.sparkContext   #创建上下文
    
    # 载入文件并转换为Row。people文件中内容是Michael, 29  Andy, 30  Justin, 19
    lines = sc.textFile("examples/src/main/resources/people.txt")  #可以读HDFS文件、本地文件或支持Hadoop文件系统的URI,返回RDD的字符串
    parts = lines.map(lambda l: l.split(","))  #以逗号分隔
    people = parts.map(lambda p: Row(name=p[0], age=int(p[1]))) #每行转换为Row
    
    # 推断数据模式,把Dataframe注册为数据库表.
    schemaPeople = spark.createDataFrame(people)
    schemaPeople.createOrReplaceTempView("people")
    
    # DataFrames注册为数据库表之后,可以使用SQL.
    teenagers = spark.sql("SELECT name FROM people WHERE age >= 13 AND age <= 19")
    
    # SQL查询的结果是Dataframe对象.
    # rdd则返回类:`pyspark.RDD` of :class:`Row`.
    teenNames = teenagers.rdd.map(lambda p: "Name: " + p.name).collect()
    for name in teenNames:
        print(name)
    # Name: Justin

      4)利用程序化方式来推测数据模式(数据类型):

    from pyspark.sql.types import *   #数据类型
    
    sc = spark.sparkContext
    
    # 载入数据并转换为Row,此处未给列名.
    lines = sc.textFile("examples/src/main/resources/people.txt")
    parts = lines.map(lambda l: l.split(","))
    # Each line is converted to a tuple.
    people = parts.map(lambda p: (p[0], p[1].strip()))
    
    # schema编码为string.
    schemaString = "name age"
    
    #StructField是个类,参数有字段名,数据类型,是否可以为空;那么fields就是个对象(实例);StructType也是个类,与StructField的数据类型保持一致,可迭代
    #StringType也是个类,还有BinaryType、 BooleanType等。此处把name、age传进去。 fields
    = [StructField(field_name, StringType(), True) for field_name in schemaString.split()] schema = StructType(fields) # 把schema应用到RDD. schemaPeople = spark.createDataFrame(people, schema) # 创建临时视图 schemaPeople.createOrReplaceTempView("people") # SQL can be run over DataFrames that have been registered as a table. results = spark.sql("SELECT name FROM people") results.show() # +-------+ # | name| # +-------+ # |Michael| # | Andy| # | Justin| # +-------+

      ???为什么要推断数据模式,因为原始的数据没有列名和数据类型,定义了列名和数据类型之后,就是DataFrame了,然后方便处理数据?

      ???尝试编代码时,总是报错,如下:

      

    ERROR:py4j.java_gateway:An error occurred while trying to connect to the Java server (127.0.0.1:58808)
    Traceback (most recent call last):
    File "C:UsersdellAnaconda3libsite-packagespy4jjava_gateway.py", line 827, in _get_connection
    connection = self.deque.pop()
    IndexError: pop from an empty deque

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
    File "C:UsersdellAnaconda3libsite-packagespy4jjava_gateway.py", line 963, in start
    self.socket.connect((self.address, self.port))
    ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。

      且在这里记下,以后找到解决方法再说。

      奇怪的是,wordCount的程序第一次运行时正常,给出结果,在运行时就一直报上述错误。貌似是Java服务只能连上一会儿,之后就断开了。

      jdk的环境变量按照网上说的,反复确认,但仍然报错。一开始装的jdk9,后又改成jdk1.8。

      

  • 相关阅读:
    一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——收流篇:(一)简介
    常用perl脚本工具
    一步步学习操作系统(2)——在STM32上实现一个可动态加载kernel的"my-boot"
    一步步学习操作系统(1)——参照ucos,在STM32上实现一个简单的多任务(“啰里啰嗦版”)
    一步步学习操作系统(1)——参照ucos,在STM32上实现一个简单的多任务(“精简版”)
    perl的正则表达式
    vim小技巧
    一些方便的bash命令
    Linux磁盘及文件系统管理
    Linux权限扩展
  • 原文地址:https://www.cnblogs.com/xiaoxiong-kankan/p/7646429.html
Copyright © 2020-2023  润新知