大数据处理技术导论(8) | Datawhale组队学习46期

本文介绍了Hive的内部表和外部表的区别,强调了数据存储和管理的差异。同时,讨论了HBase作为数据存储引擎与Hive作为数据分析引擎的不同应用场景。此外,文章探讨了Spark与HadoopMapReduce在计算效率上的优势,以及Spark的宽窄依赖概念。最后,提出了一个使用PySpark进行文本数据分析的实战任务,涉及TF-IDF模型来计算每年的热门词汇。
摘要由CSDN通过智能技术生成


项目地址 https://github.com/datawhalechina/juicy-bigdata,感谢项目团队的付出。
本次学习任务是完成 期末大作业

10. 1 面试题

10.1.1 hive外部表和内部表的区别

hive 内部表和外部表的差异总结如下:

对比内容内部表外部表
数据存储位置内部表数据存储的位置由 hive-site.xml 中的hive.Metastore.warehouse.dir参数指定,
默认情况下,表的数据存储在HDFS/user/hive/warehouse/数据库名.db/表名/目录下
外部表数据的存储位置创建表时由Location参数指定
导入数据在导入数据到内部表,内部表将数据移动到自己的数据仓库目录下,
数据的生命周期由Hive来进行管理
外部表不会将数据移动到自己的数据仓库目录下,
只是在元数据中存储了数据的位置
删除表删除元数据(metadata)和 HDFS 数据文件只删除元数据(metadata)
安全性低(容易误删数据)

10.1.2 简述对Hive桶的理解?

hive 分桶是基于 hive 表指定列进行 hash,根据不同的 hash 值进行分组,将数据文件分割为若干小文件。
优点是优化 join 查询和抽样查询,缺点是会生成很多小文件。

10.1.3 HBase和Hive的区别?

hbase 是数据存储引擎,hive 是数据分析引擎。
hbase 适用于海量数据高吞吐、低时延的存储和读取。
hive 适用于利用易用性好的 SQL 对存储于 hdfs 上半结构化或者非结构化的海量数据进行查询与分析。

10.1.4 简述Spark宽窄依赖

Spark中计算阶段划分的依据是Shuffle,而不是操作函数的类型,并不是所有的函数都有Shuffle过程。
Spark把不需要Shuffle的依赖,称为窄依赖需要Shuffle的依赖,称为宽依赖

10.1.5 Hadoop和Spark的相同点和不同点

hadoop 是大数据框架,侧重于数据存储,也支持计算,通过 mapreduce 将计算过程划分为 map 和 reduce 两个阶段。
Spark 是大数据计算框架,侧重于计算,它没有分布式文件系统,必须依赖于其他数据源系统。和 mapreduce 类似,spark 也是将计算过程拆分为 map 、reduce 两个阶段。

10.1.6 Spark为什么比MapReduce快?

  • 编程模型方面
    hadoop mapreduce 根据 shuffle 将大数据计算过程拆分为 map 和 reduce 两个阶段,而 spark 流程更加流畅,它是将前一个 reduce 结果和后一个 map 进行连接,当作一个阶段进行计算处理,从而形成了一个更加高效的数据模型,减少了对 hdfs 的访问次数,减少了作业的调度执行次数。
  • 存储方式方面
    hadoop mapreduce 主要使用 磁盘 存储 shuffle 过程产生的数据,而 spark 优先使用内存进行数据的存储(RDD也是优先存储于内存),这是 spark 比 mapreduce 更快的另一个原因。

10.1.7 说说你对Hadoop生态的认识

hadoop 生态是现如今大数据处理的基石。了解和掌握 hadoop 生态组件是学习大数据处理的必经之路。hadoop 生态相关的组件一直在高速发展,拥抱变化。我们要跟紧 hadoop 生态发展的步伐,努力学习最实用、最先进的大数据处理技术和组件。

10.2 实战

从新闻文章中发现热门话题和趋势话题是舆论监督的一项重要任务。在这个项目中,你的任务是使用新闻数据集进行文本数据分析,使用 Python 中 pySpark 的 DataFrame 和 RDD 的 API。问题是计算新闻文章数据集中每年各词的权重,然后选择每年 top-k个最重要的词。

10.2.1 数据集

您将使用的数据集包含多年来发布的新闻标题数据。在这个文本文件中,每一行都是一篇新闻文章的标题,格式为“ date,term1 term2… …”。日期和文本用逗号分隔,文本用空格字符分隔。示例文件如下:

20030219,council chief executive fails to secure position
20030219,council welcomes ambulance levy decision
20030219,council welcomes insurance breakthrough
20030219,fed opp to re introduce national insurance
20040501,cowboys survive eels comeback
20040501,cowboys withstand eels fightback
20040502,castro vows cuban socialism to survive bush
20200401,coronanomics things learnt about how coronavirus economy
20200401,coronavirus at home test kits selling in the chinese community
20200401,coronavirus campbell remess streams bear making classes
20201015,coronavirus pacific economy foriegn aid china
20201016,china builds pig apartment blocks to guard against swine flu

10.2.2 文本权重计算

您需要忽略诸如“ to”、“ the”和“ in”之类的停用词。该文件存储了停用词。

为了计算一个文本的为期一年的权重,请使用 TF/IDF 模型。具体而言,TF 和 IDF 可计算为:

T F ( 文本 t , 年份 y ) = 在 y 年份中,包含文本 t 的新闻标题数量 TF(文本 t, 年份 y) = 在 y 年份中,包含文本 t 的新闻标题数量 TF(文本t,年份y)=y年份中,包含文本t的新闻标题数量

I D F ( 文本 t , 数据集 D ) = l o g 10 ( 在数据集 D 中年份的总数 / 含有文本 t 的年份总数 ) IDF(文本 t,数据集 D) = log10(在数据集D中年份的总数/含有文本t的年份总数) IDF(文本t,数据集D)=log10(在数据集D中年份的总数/含有文本t的年份总数)

最后,文本 t 对于年份 y 的权重计算如下:

W e i g h t ( 文本 t , 年份 y , 数据集 D ) = T F ( 文本 t , 年份 y ) ∗ I D F ( 文本 t , 数据集 D ) Weight(文本 t, 年份 y, 数据集 D) = TF(文本 t, 年份 y)* IDF(文本 t, 数据集 D) Weight(文本t,年份y,数据集D)=TF(文本t,年份y)IDF(文本t,数据集D)

请使用 import math 并使用 math.log10()计算文本权重,并将结果四舍五入到小数点后6位。

10.2.3 输出格式

如果数据集中有 N 年,那么您应该在最终输出文件中输出正好 N 行,并且这些行按年份升序排序。在每一行中,您需要以<term, weight> 的格式输出 k 对list,并且这些对按照文本权重降序排序。如果两个文本具有相同的权重,则按字母顺序对它们进行排序。具体来说,每行的格式类似于:
“year**\t** Term1,Weight1;Term 2,Weight2;… …;Termk,Weightk” 。例如,给定上述数据集和 k = 3,输出应该是:

2003 council,1.431364;insurance,0.954243;welcomes,0.954243
2004 cowboys,0.954243;eels,0.954243;survive,0.954243
2020 coronavirus,1.908485;china,0.954243;economy,0.954243

10.2.4 运行指令

Dataframe:

spark-submit project_df.py file:///testcase_top20/sample.txt file:///res_df file:///stopwords.txt k

RDD:

spark-submit project_rdd.py file:///testcase_top20/sample.txt file:///res_rdd file:///stopwords.txt k

其中 file://后跟随本地文件目录地址。

10.2.5 程序补全

Dataframe:

from pyspark.sql.session import SparkSession
from pyspark.sql.functions import *
import sys


def takeTopK(pairList, k):
    #填入获得前k个排名的函数
    pairList.show(k)

class Project2:

    def run(self, inputpath, outputpath, stopwords, k):
        spark = SparkSession.builder.master("local").appName("project2_df").getOrCreate()

        #填入以下两个函数的参数
        fileDF = spark.read.text(inputpath)
        swlist = spark.sparkContext.broadcast(stopwords)

        headlineDF = fileDF.select(split(fileDF['value'], ',').getItem(0).substr(0, 4).alias('year'),
                                   split(fileDF['value'], ',').getItem(1).alias('headline'))
        headlineDF = headlineDF.withColumn('word', split('headline', ' '))
        headlineDF2 = headlineDF.select('year', array_distinct(headlineDF.word).alias('word'))
        headlineDF3 = headlineDF2.withColumn('word', explode('word'))

        yearwordsDF = headlineDF3[~headlineDF3.word.isin(swlist.value)]
        #写出TF计算的函数
        TF =
        totalYear = yearwordsDF.select('year').distinct().count()
        #写出DF计算的函数
        DF =
        TFIDF = TF.join(DF, TF.word == DF.word).select(TF.year, TF.word, TF.TF, DF.DF)

        weightDF = TFIDF.withColumn('weight', round(TFIDF.TF * log10(totalYear / TFIDF.DF), 6)).select('year', 'word',
                                                                                                       'weight')
        groupDF = weightDF.groupBy('year').agg(collect_list(struct('word', 'weight')).alias('pair'))
        topkUDF = udf(lambda z, k: takeTopK(z, k))
        res = groupDF.withColumn('pair', topkUDF('pair', lit(int(k)))).orderBy('year')
        res2 = res.coalesce(1).orderBy('year').withColumn('result', concat_ws('\t', 'year', 'pair')).select('result')
        res2.write.text(outputPath)
        spark.stop()

if __name__ == "__main__":
    if len(sys.argv) != 5:
        print("Wrong arguments")
        sys.exit(-1)
    Project2().run(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])

RDD:

from pyspark import SparkContext, SparkConf
from operator import add
from math import log10
import heapq
import sys


def takeTopK(pairList, k):
    #填入获得前k个排名的函数
    pairList.show(k)

class Project2:

    def run(self, inputpath, outputpath, stopwords, k):
        conf = SparkConf().setAppName("project2_rdd")
        sc = SparkContext(conf=conf)

        # 填入以下两个函数的参数
        filerdd = sc.textFile(inputpath)
        swlist = sc.broadcast(stopwords)

        #写出以下标题、年度词、TF、总年计算的函数
        headlines =
        yearwords =
        TF =
        totalYear =

        # DF = yearwords.map(lambda x:(x[0][1], x[0][0])).countByKey()
        DF = yearwords.map(lambda x: (x[0][1], x[0][0])).groupByKey().map(lambda x: (x[0], len(x[1])))

        TFIDF = TF.join(DF).map(lambda x: (x[1][0][0], (round(x[1][0][1] * log10(totalYear / x[1][1]), 6), x[0])))
        res = TFIDF.groupByKey().map(lambda x: (x[0], list(x[1]))).mapValues(lambda x: takeTopK(x, int(k)))
        res2 = res.coalesce(1).sortByKey().map(
            lambda x: f'{x[0]}\t{";".join([item[1] + "," + str(item[0]) for item in x[1]])}')

        res2.saveAsTextFile(outputPath)
        sc.stop()

if __name__ == "__main__":
    if len(sys.argv) != 5:
        print("Wrong arguments")
        sys.exit(-1)
    Project2().run(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值