Hive 的 UDF 函数(Python 版本)

这篇具有很好参考价值的文章主要介绍了Hive 的 UDF 函数(Python 版本)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Hive 的 UDF 函数(Python 版本)

一、UDF 是什么

Hive 中支持很多的函数,可以极大的方便我们的工作。但是系统内置的函数虽然很多,却不能满足我们所有的需求。在遇到一些个性化需求的时候,系统内置的函数无法满足,此时就需要使用代码来完成自己的业务逻辑。

UDF: User Defined Function,字面来理解就是用户自定义的函数。其实展开来说,很多系统内置的函数也属于是 UDF 函数。UDF 函数的最大特点是“一对一”。即:一行输入、一行输出。例如,month 函数可以获取到一个日期中的月份。如果我们使用 month(birthday) 就可以获取到一个生日字段中的月份。一行数据中的生日的数据,带入到 month 函数中,就可以得到一行的月份信息。

UDAF: User Defined Aggregation Function,字面来理解就是用户自定义的聚合函数。其实展开来说,常见的聚合函数也属数据 UDAF 函数的。例如 sum, count, max, min, avg,这些函数是作用于某一列的多行数据的。接受多行数据的输入,输出一行的聚合结果。

UDTF: User Defined Table Generate Function,字面来理解就是用户自定义的表生成函数。这种函数可以接受一行的输入数据,输出多行的结果。例如 Hive 中的 explode 就是这样的函数,可以接受一个数组或者字典的数据,将其中的数据展开成多行。

二、UDF 函数的实现

Hive 本身是用 Java 语言来编写的,提供的 UDF 函数的接口也是 Java 的编程接口。但是 Hive 也同时提供了对 Python 的支持,使得可以使用 Python 的语言来编写自己的 UDF、UDAF、UDTF 的逻辑,并且实现起来比 Java 的更加简单!

本文只是记录 UDF 函数的 Python 实现版本!

Python 实现的 UDF、UDAF、UDTF 函数,需要对输入的一整行的数据进行处理,而并不是针对某一个字段进行处理!

  • 读取每一行的输入:可以使用 Python 中的标准输入流来读取。需要注意的是,无论 Hive 的表中是以什么样的字符进行分隔的,这里读取到的字段之间始终是以 \t 进行分隔的!因此我们也必须要使用 \t 进行字段的切割。
  • 输出一行的数据:在将一整行的数据处理完成之后,如果需要输出的时候,直接使用 print 函数打印即可。与输入的一样,输出的不同的字段之间也必须要使用 \t 进行分隔!
  • UDAF 函数实现、UDTF 函数实现:如果实现 UDAF、UDTF 这种输入行和输出行不一致的情况,直接控制 print 函数的输出次数即可。一次的 print 就会生成一行的数据,因此合理控制 print 函数的调用次数,即可实现 UDAF、UDTF 函数。
三、UDF 函数案例
案例一、将字母转成全部大写

1、准备数据文件

zhangsan,male,19
lisi,female,20
wangwu,male,18
zhaoliu,female,19

2、创建数据表

create table if not exists example_01(
	t_name string,
	t_gender string,
	t_age int
)
row format delimited
fields terminated by ',';

3、代码编写

# -*- coding: utf-8 -*-
# @Author   : 大数据章鱼哥
# @Company  : 北京千锋互联科技有限公司

# string_upper.py
import sys

for line in sys.stdin:
    print(line.upper(), end='')

4、应用函数

-- 应用UDF
add file string_upper.py

-- 查询名字,将其转成大写
select transform(t_name) using 'python3 string_upper.py' as (t_name) from example_01;
-- 查询名字、性别,将其转成大写
select transform(t_name, t_gender) using 'python3 string_upper.py' as (t_name, t_gender) from example_01;
案例二、只需要将姓名转成大写

1、数据准备

数据文件和表,沿用案例一即可

2、代码编写

# -*- coding: utf-8 -*-
# @Author   : 大数据章鱼哥
# @Company  : 北京千锋互联科技有限公司

# string_name_upper.py
import sys

for line in sys.stdin:
    # 1. 切割出来每一列
    columns = line.strip().split('\t')
    # 2. 判断切割出来的列的数量,如果数量不正确,这一行数据不处理
    length = len(columns)
	name = columns[0].upper() if length >= 1 else 'NULL'
    gender = columns[1] if length >= 2 else 'NULL'
    age = columns[2] if length >= 3 else 'NULL'
    
    # 3. 打印处理之后的结果
    print('\t'.join([name, gender, age]))

3、应用函数

-- 查询所有字段,将名字转成大写
select transform(*) using 'python3 string_name_upper.py' as (name, gender, age) from example_01;

+-----------+---------+------+
|   name    | gender  | age  |
+-----------+---------+------+
| ZHANGSAN  | male    | 19   |
| LISI      | female  | 20   |
| WANGWU    | male    | 18   |
| ZHAOLIU   | female  | 19   |
+-----------+---------+------+
案例三、身份证解析

1、准备数据文件

身份证号码是按照身份证的规则随机生成,如有雷同,纯属巧合。

张三三,410023198911223344
李思思,110011200210103232
汪呜呜,37126520000223987X
赵溜溜,561276199512019866

2、准备数据表

create table if not exists example_02(
	username string,
	idcard string
)
row format delimited
fields terminated by ',';

3、 代码编写

需求:通过表中的数据,查询出 姓名、身份证号、出生年月日、年龄、性别

# -*- coding: utf-8 -*-
# @Author   : 大数据章鱼哥
# @Company  : 北京千锋互联科技有限公司

# 身份证验证
#   如果身份证不是一个合法的身份证,输出空
#   如果身份证是合法的,解析出年龄、生日、性别

import sys
import re
import datetime

def calculate_age(year, month, day):
    now = datetime.datetime.now()
    age = now.year - year
    if now.month < month:
        age -= 1
    elif now.month == month and now.day < day:
        age -= 1
    return age

for line in sys.stdin:
    # 1. 切割出来每一个组成部分
    fields = line.strip().split('\t')
    # 2. 如果长度不到两位,说明数据有问题,不做任何处理
    if len(fields) != 2:
        continue
    # 3. 提取姓名和身份证
    name = fields[0]
    id_card = fields[1]
    # 4. 身份证正则匹配
    m = re.fullmatch(r'(\d{6})(?P<year>(19|20)\d{2})(?P<month>0[1-9]|1[0-2])(?P<day>[012][0-9]|10|20|30|31)\d{2}(?P<gender>\d)[0-9xX]', id_card)
    if m is None:
        print('\t'.join([name, id_card, 'NULL', 'NULL', 'NULL']))
    else:
        # 出生年月日
        year = m.group('year')
        month = m.group('month')
        day = m.group('day')
        age = calculate_age(int(year), int(month), int(day))
        # 计算性别
        gender = '男' if int(m.group('gender')) % 2 != 0 else '女'
        # 拼接生日
        birthday = f'{year}-{month}-{day}'
        print('\t'.join([name, id_card, birthday, str(age), gender]))

4、应用函数

-- 添加文件
add file idcard_parser.py
-- 执行查询
select transform(*) using 'python3 idcard_parser.py' as (name, idcard, birthday, age, gender) from example_02
    
+-------+---------------------+-------------+------+---------+
| name  |       idcard        |  birthday   | age  | gender  |
+-------+---------------------+-------------+------+---------+
| 张三三 | 410023198911223344  | 1989-11-22  | 33   ||
| 李思思 | 110011200210103232  | 2002-10-10  | 20   ||
| 汪呜呜 | 37126520000223987X  | 2000-02-23  | 22   ||
| 赵溜溜 | 561276199512019866  | 1995-12-01  | 27   ||
+-------+---------------------+-------------+------+---------+
四、UDAF 函数案例

1、数据准备

zhangsan,89
lisi,67
wangwu,55
zhaoliu,78
tianqi,92

2、建立数据表

create table if not exists example_03(
	name string,
	score int
)
row format delimited
fields terminated by ',';

3、代码编写

需求:通过表中的数据,统计出学生的人数、总成绩、最高成绩、最低成绩、平均成绩、及格率

# -*- coding: utf-8 -*-
# @Author   : 大数据章鱼哥
# @Company  : 北京千锋互联科技有限公司

import sys

scores = []

for line in sys.stdin:
    scores.append(int(line.strip()))

# 计算人数
count = len(scores)
# 计算总成绩
sum_score = sum(scores)
# 计算最高成绩
max_score = max(scores)
# 计算最低成绩
min_score = min(scores)
# 计算平均成绩
avg_score = sum_score / count
# 计算及格率
rate = len(list(filter(lambda x: x >= 60, scores))) / count

# 输出最后的结果
print('\t'.join(map(lambda x: str(x), [count, sum_score, max_score, min_score, avg_score, rate])))

4、应用函数

-- 添加文件
add file my_agg.py
-- 执行查询
select transform(*) using 'python3 my_agg.py' as (count, sum_score, max_score, min_score, avg_score, rate) from example_03
五、UDTF 函数案例

1、准备数据

zhangsan 78,89,92,96
lisi 67,75,83,94
王五 23,12

2、建立数据表

create table if not exists example_04(
name string,
scores array<String>
)
row format delimited 
fields terminated by ' '
collection items terminated by ','
;

3、 需求实现

需求:根据表中的数据,将每一个成绩展开,绑定给每一个名字

# -*- coding: utf-8 -*-
# @Author   : 大数据章鱼哥
# @Company  : 北京千锋互联科技有限公司

import sys

for line in sys.stdin:
    fields = line.strip().split('\t')
    if len(fields) != 2:
        continue
    # 提取名字
    name = fields[0]
    # 提取所有成绩
    scores = fields[1].strip('[').rstrip(']').split(',')
    for s in scores:
        print("\t".join([name, s]))

4、函数应用文章来源地址https://www.toymoban.com/news/detail-712475.html

-- 添加文件
add file my_explode.py
-- 执行查询
select transform(*) using 'python3 my_explode.py' as (name, score) from example_04

到了这里,关于Hive 的 UDF 函数(Python 版本)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 大数据开发之Hive案例篇9-Not yet supported place for UDAF ‘count‘

    一个很简单的group by和count(*) 操作,然后居然报错了 大概是在Oracle MySQL上写SQL写习惯了,以为可以这么写。 出了问题也是不知道从何排查 后面把order by子句注释掉之后,居然就可以了,那么就是order by 后面不能跟聚合函数了 于是使用了聚合函数的别名,问题搞定 修改为如下

    2024年02月06日
    浏览(50)
  • 7、hive shell客户端与属性配置、内置运算符、函数(内置运算符与自定义UDF运算符)

    1、apache-hive-3.1.2简介及部署(三种部署方式-内嵌模式、本地模式和远程模式)及验证详解 2、hive相关概念详解–架构、读写文件机制、数据存储 3、hive的使用示例详解-建表、数据类型详解、内部外部表、分区表、分桶表 4、hive的使用示例详解-事务表、视图、物化视图、DDL

    2024年02月09日
    浏览(45)
  • Hive UDF

    当Hive提供的内置函数不能满足查询需求时,用户可以根据自己业务编写自定义函数(User Defined Functions, UDF), 然后在HiveQL中调用。 例如有这样一个需求:为了保护用户隐私,当查询数据的时候,需要将用户手机号的中间四位用*号代替,比如手机号18001292688需要显示为180****268

    2024年02月22日
    浏览(40)
  • hive udf 判断四边形是否为矩形

    hive udf中经常要做判断四边形是否为矩形,所以写了这个udf如下:

    2024年02月12日
    浏览(38)
  • hql、数据仓库、sql调优、hive sql、python

    HQL(Hibernate Query Language) 是面向对象的查询语言 SQL的操作对象是数据列、表等数据库数据 ; 而HQL操作的是类、实例、属性 数据仓库的定义 英文名称为Data Warehouse,可简写为DW或DWH。 为企业级别的决策制定过程,提供所有类型数据支持的战略集合。 它出于分析性报告和决策支持

    2024年02月03日
    浏览(63)
  • 【Hive+MySQL+Python】淘宝用户购物行为数据分析项目

    user_data.csv是一份用户行为数据,时间区间为2017-11-25到2017-12-03,总计29132493条记录,大小为1.0G,包含5个字段。数据集的每一行表示一条用户行为,由用户ID、商品ID、商品类目ID、行为类型和时间戳组成,并以逗号分隔。关于数据集中每一列的详细描述如下: 用户行为类型共

    2024年02月07日
    浏览(43)
  • 【Python大数据笔记_day05_Hive基础操作】

     用户在hive上编写sql语句,hive把sql语句转化为MapReduce程序去执行 用户接口:         包括CLI、JDBC/ODBC、WebGUI,CLI(command line interface)为shell命令行;Hive中的Thrift服务器允许外部客户端通过网络与Hive进行交互,类似于JDBC或ODBC协议。WebGUI是通过浏览器访问Hive。         --Hive提供

    2024年01月22日
    浏览(31)
  • 【大数据Hive】Hive 窗口函数使用详解

    目录 一、前言 二、hive 窗口函数概述 2.1 聚合函数与窗口函数差别 2.1.1 创建一张表

    2024年02月11日
    浏览(38)
  • 【大数据之Hive】十六、Hive-HQL函数之窗口函数(开窗函数)

      先定义了窗口的大小(按行来算),然后对窗口内的行的数据进行计算,再将计算结果返回给改行。   窗口函数包括窗口和函数两部分,窗口用于定义计算范围,函数用于定义计算逻辑,窗口函数只会在原来的表上增加一列结果列,不改变原来的数据。 函数:   绝

    2024年02月11日
    浏览(39)
  • 【大数据之Hive】十三、Hive-HQL函数之单行函数和高级聚合函数

      Hive内置函数:单行函数、聚合函数、炸裂函数、窗口函数。   单行函数的特点是一进一出,即输入一行,输出一行;包括算数运算函数、数值函数、字符串函数、日期函数、流程控制函数、集合函数等。 3.1 substring 截取字符串 语法: 3.2 replace 全局替换 语法: 3.3 re

    2024年02月09日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包