社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

使用 Python进行文本分析来检验一个假设

Python程序员 • 4 年前 • 294 次点击  


人们经常抱怨新闻中对重要的主题报道得太少。其中一个主题就是气候变化。科学上的共识是,这是一个重要的问题,而且人们有理由认为,越多的人意识到它,我们解决它的机会就越大。但我们如何评估各种媒体对气候变化的报道有多广泛呢?我们可以使用Python进行一些文本分析!


具体来说,在这篇文章中,我们将尝试回答哪家新闻媒体对气候变化报道的最多。同时,我们将学习使用Python分析文本数据的一些技巧,并测试与该数据相关的一个假设。


本教程假设你非常熟悉Python和流行的数据科学包pandas。如果你想重温一下pandas,请查看这篇文章,如果你需要构建更全面的基础,Dataquest的交互课程将更深入地涵盖所有Python和pandas基础。


发现&研究我们的数据集


在这篇文章中,我们将使用Andrew Thompson提供的来自Kaggle的新闻数据集(没有关联)。该数据集包含超过14.2万篇文章,来自15个来源,大部分来自2016年和2017年,并被分成三个不同的csv文件。以下是Andrew在Kaggle 概览页面上展示的文章数量:



稍后,我们将复制我们自己的版本。但有一件事或许值得关注,那就是这些新闻媒体的特点与它们发表的与气候变化相关的文章的比例之间的相关性。


我们可以看看一些有趣的特征,包括所有权(独立、非盈利或公司)和政治倾向(如果有的话)。下面,我做了一些初步的研究,我是从维基百科和供应商自己的网页上收集的信息。

我还发现了两个网站,allsides.com和mediabiasfactcheck.com,它们对出版物的自由派和保守派倾向进行了评分,所以我从那里收集了一些有关政治倾向的信息。


  • Atlantic:

    • Owner: Atlantic Media; majority stake recently sold to Emerson collective, a non-profit founded by Powell Jobs, widow of Steve Jobs

    • Lean Left

  • Breitbart:

    • Owner: Breitbart News Network, LLC

    • Founded by a conservative commentator

    • Right

  • Business Insider:

    • Owner: Alex Springer SE (publishing house in Europe)

    • Center / left-center

  • Buzzfeed News:

    • Private, Jonah Peretti CEO & Kenneth Lerer, executive chair (latter also co-founder of Huffington Post)

    • Lean left

  • CNN:

    • Turner Broadcasting System, mass media

    • TBS itself is owned by Time Warner

    • Lean left

  • Fox News:

    • Fox entertainment group, mass media

    • Lean right / right

  • Guardian:

    • Guardian Media Group (UK), mass media

    • Owned by Scott Trust Limited

    • Lean left

  • National Review:

    • National Review Institute, a non-profit

    • Founded by William F Buckley Jr

    • Right

  • New York Post:

    • News corp, mass media

    • Right / right center

  • New York Times:

    • NY Times Company

    • Lean Left

  • NPR:

    • Non-profit

    • Center / left-center

  • Reuters:

    • Thomson Reuters Corporation (Canadian multinational mass media)

    • Center

  • Talking points memo:

    • Josh Marshall, independent

    • Left

  • Washington Post:

    • Nash Holdings LLC, controlled by J. Bezos

    • Lean left

  • Vox:

    • Vox Media, multinational

    • Lean left / left

仔细研究一下,我们可能会假设右倾的Breitbart与气候相关的文章所占的比例,会比NPR等媒体要低。


我们可以把它变成一个正式的假设陈述,我们会在后面做。但首先,让我们更深入地研究数据。一个术语需要注意:在计算语言学和NLP社区中,像这样的文本集合称为语料库,所以在本文中讨论文本数据集时,我们将使用这个术语。


探索性数据分析(EDA)是任何数据科学项目的重要组成部分。它通常涉及以各种方式分析和可视化数据,以便在进行更深入的分析之前寻找模式。不过,在本例中,我们使用的是文本数据而不是数字数据,这使得情况有些不同。


例如,在数值探索性数据分析中,我们通常希望查看数据特性的平均值。但是在一个文本数据库中是不存在“平均”这个词的,这使得我们的任务更加复杂。然而,我们仍然可以进行定量和定性的研究来检查我们的语料库的一致性。

首先,让我们重新生成上面的图表,以确保没有遗漏任何数据,然后按文章数量进行排序。我们将从覆盖所有导入开始,读取数据集,并检查其三个部分的长度。



不过,使用三个独立的数据集并不方便。我们将把所有三个DataFrame合并成一个,这样我们就可以更容易地使用整个语料库:



接下来,我们将确保拥有与原始数据集中相同的发布名称,并检查最早年份和最新年份的文章。



像上面看到的那样将日期存储为浮点数是不常见的,但我们的CSV文件中就是按这种方式来存储的。不管怎样,我们并不打算在任何特别重要的地方使用日期,因此出于本教程的目的,我们将它们保留为浮点数。但是,如果我们在进行不同的分析,我们可能会希望将它们转换成不同的格式。


我们使用pandas的value_counts()函数来快速查看下我们的文章是什么时候的。



我们可以看到大部分是最近几年的文章,但是也包括了一些较老的文章。这很好地达到了我们的目的,因为我们主要关注过去几年的报道。


现在,我们按名称对出版物进行排序,以重现Kaggle中的原始图表。




如果你想快速找到一个特定的头条,这个图表顺序是有用的,但是按文章计数对其进行排序可能更有用,这样我们就能更好地了解我们的数据的来源。



我们想要按单词来检查平均文章长度,但同样重要的是这些单词的多样性。我们来看看两者。


我们将从定义一个函数开始,该函数会删除标点符号并将所有文本转换为小写。(我们没有做任何复杂的句法分析,所以我们不需要保留句子结构或大写)。



现在,我们将在我dataframe中创建一个新列,其中包含已清洗的文本。



在上面,我们可以看到我们已经成功地从语料库中删除了大写字母和标点符号,这将使我们能更容易地识别和计数独特字。


我们来看看每篇文章的平均(平均值)字数,以及我们数据集中最长和最短的文章。



一篇没有单词的文章对我们没有任何用处,所以让我们看看有多少这样的文章。我们希望从数据集中删除没有单词的文章。



让我们去掉这些空文章,然后看看这对我们数据集中每篇文章的平均字数有什么影响,以及新的最小字数是多少。



在这一点上,它可能有助于我们可视化文章字数的分布,以了解我们的离群值对平均值的影响有多大。让我们生成另一个图表来看看:


我们的Python文本分析的下一步是:探究文章的多样性。我们将以每篇文章中独特字的数量作为开始。要计算这个值,我们需要创建一个文章中单词的集合,而不是列表。我们可以将这个集合看作有点像列表,但是集合会省略重复的条目。


在官方文档中有更多关于集合及其工作原理的信息,但我们先看一个关于如何创建一个集合的基本示例。注意,虽然我们是从两个b条目开始的,但在我们创建的集合中只有一个:



接下来,我们马上要做几件事:


对前面创建的tokenized的列中的系列进行操作,我们将从 string库调用 split函数。然后我们将从我们的系列中获取集合以消除重复的单词,然后使用len()测量集合的大小。


最后,我们将把结果添加到一个新列中,其中包含每篇文章中独特字的数量。



我们还想看看每篇文章的独特字的平均字数,以及最小和最大的独特字计数。



当我们将其绘制成图表时,我们可以看到,尽管独特字的分布仍然是歪斜的,但它看起来更像一个正态分布(高斯分布),而不是基于我们之前生成的单词总数的分布。



我们也来看看这两个度量文章长度的方法在不同的出版物中是如何变化的。


为此,我们将使用pandas的groupby函数。关于这个功能强大的函数的完整文档可以在这里找到,但是对我们这里的目的来说,我们只需要知道它允许我们通过另一列的值以不同的方式不同的度量标准来进行aggregate(合计)或求总和。


在本例中,这个列就是publication。第一个图表通过对len进行合计只使用每个组中的对象数量。我们可以在下面的代码中使用除title之外的任何其他列。



现在我们将分别对单词的平均数和独特字数量进行合计。



最后,我们来看看整个语料库中最常见的单词。


我们将使用一个Python Counter,这是一种特殊的字典,它假定每个键的值为整数类型。在这里,我们将使用文章的标记化版本来遍历所有文章。



但是,当我们在计数最常见的单词时,我们并不想把所有的单词都包括在我们的计数中。在书面英语中,有许多单词是如此常见,以至于在任何分析中,它们都很可能是最常见的单词。对它们进行计数并不能告诉我们关于文章内容的任何信息。在NLP和文本处理中,这些单词被称为“stopwords”。常见的英语stopwords停顿词列表包括“and”、“or”和“such”等单词。


记得我们在这个项目开始的地方从nltk.corpus导入了stopwords模块,所以现在我们来看看什么单词包含在这个预先制作的stopwords列表中:



正如我们所见,这是一个很长的列表,没有一个词可以确切告诉我们一个文章的意思。我们使用这个列表来删除Counter中的stopword。



为了进一步过滤我们的单词计数来得到有用的信息,Counter有一个方便的most_common方法,我们可以在这里使用它来查看Counter找到的最常用的单词。使用这个函数,我们可以指定想要查看的结果的数量。在这里,我们将要求它列出最常见的20个单词。



在上面,我们可以看到一些非常容易预测到的单词,但也有一点令人惊讶: u显然是最常见的单词之一。这听起来可能有些奇怪,但它就是从文章中经常使用“U.S.”和“U.N.”这样的缩写词这一事实中得出来的。


这有点奇怪,但请记住,目前我们只是在研究数据。我们想要检验的实际假设是: 气候变化报道可能与媒体的某些方面有关,比如其所有权或政治倾向。在我们的语料库中,u作为一个单词的存在根本不可能影响这个分析,所以我们可以让它保持原样。


我们还可以在其他领域对这个数据集进行更多的清理和细化,但这可能没有必要。相反,让我们进入下一步:测试我们最初的假设是否正确。


文本分析: 检验我们的假设


我们如何检验我们的假设?首先,我们必须确定哪些文章是关于气候变化的,然后我们必须通过文章类型来比较这些报道。


我们如何判断一篇文章是否在谈论气候变化?有几种方法可以做到这一点。我们可以使用高级文本分析技术(如集群或主题建模)来识别概念。但是对于本文的目的来说,我们保持简单一些:让我们只识别可能与主题相关的关键字,并在文章中搜索它们。只要头脑风暴一些有趣的单词和短语就可以了。


当我们列出这些短语时,我们必须小心避免使用诸如“环境”或“可持续性”之类的模糊词汇。这些词汇可能与环保主义有关,但也可能与政治环境或商业可持续性有关。即使是“气候”也可能不是一个有意义的关键词,除非我们能确定它与“变化”密切相关。


我们需要做的是创建一个函数来确定一篇文章是否包含我们感兴趣的单词。为此,我们将使用regex,也叫正则表达式。如果你需要复习一下,本文更详细地介绍了Python中的正则表达式。除了这个Regex,我们还将搜索cc_wds参数中定义的其他几个短语的精确匹配。


在寻找有关气候变化的话题时,我们必须谨慎一点。我们不能用“change”这个词,因为那样会把“changing”这类相关的词去掉。


因此,下面是我们如何过滤它的过程: 我们想要在1到5个单词之内找到后面跟着chang字符串的climate字符串(在正则表达式中,\w+会匹配一个或多个单词字符,而\W+会匹配一个或多个非单词字符)。


我们可以使用 | 来表示逻辑or,所以我们也可以在1到5个单词之内匹配到后面跟着chang字符串的climate字符串。1到5个单词的部分是正则表达式的一部分,它看起来像这样:(?:\w+\ W+){1,5}?。


总之,搜索这两个字符串可以帮助我们识别任何提到气候变化、正在变化的气候等的文章。



这里详细展示了这个函数部分是如何运行的:



正如我们所看到的,这一切都在按计划进行——它与气候变化的真实含义相匹配,而不是因“变化”一词在其他语境中的使用而被抛弃。


现在,让我们使用我们的函数创建一个新的布尔字段来指示我们是否找到了相关的单词,然后看看在我们的数据集中的前五篇文章中是否提到了气候变化:



我们数据集中的前五篇文章没有提到任何关于气候变化的内容,但是我们知道我们的函数在按照我们之前测试的预期运行,所以现在我们可以开始对新闻报道进行一些分析。


回到我们最初的目标,即比较不同来源的有关气候变化主题的报道,我们可以考虑计算每个来源发表的气候相关文章的数量,并对不同来源进行比较。但是,当我们这样做时,我们需要考虑文章总数的差异。如果来自一个新闻报道的气候相关的文章数量较大,可能只是因为该新闻报道总体上发表的文章数量更多。


我们需要做的是计算气候相关文章的相对比例。我们可以在布尔字段(如cc_wds)上使用sum函数来计算True值的数量,并用它除以已发表文章的总数以得到我们的比例。


让我们从查看所有来源的总比例开始,并以此作为一个基线来比较每个新闻报道:



我们看到有关气候报道的文章在所有文章中的比例为3.1%,这是一个相当低的比例,但从统计学的角度来看这并没有什么问题。


接下来我们要计算每组的相对比例。让我们通过查看每个发布源的比例来用图示说明这是如何工作的。我们将再次使用groupby对象和sum,但这次我们想要每个组的文章数量,我们可以通过count函数得到:



现在,让我们将表中数据分解成比例,并对列表进行排序,这样我们就可以快速地看到哪些媒体对气候变化的报道最多:



这一比例从NewYorkPost的0.7%到Vox的8%不等。我们来绘制图表,先按发布名称排序,然后再按值排序。




我们还可以做其他各种探索性的数据分析,但我们先把这些放在一边,继续我们的目标,即校验一个关于我们的语料库的假设。


检验假设


在这篇文章中,我们不会对假设检验及其细微之处做一个完整的叙述;要了解Python中的概率论,请访问这篇文章,而对于统计假设检验的详细信息,Wikipedia是一个不错的继续学习的地方。


我们将在这里演示一种形式的假设检验。


回想一下,我们一开始非正式地假设出版特征可能与他们所发表的与气候相关的文章的优势有关。这些特征包括政治倾向和所有权。例如,我们与政治倾向有关的零假设非正式地说明,在比较具有不同政治倾向的文章时,在提及气候变化这一方面它们是没有区别的。我们来更正式一点的说。


如果我们看一下出版物的左倾和右倾的政治倾向,我们将左倾的出版物称为“左”,右倾的出版物称为“右”,我们的零假设是,“左”的气候变化文章数量比例等于“右”的气候变化文章数量比例。我们的备择假设是这两个总体的比例是不相等的。我们可以用其他群体分组和相似的假设来代替其他政治倾向比较或其他出版特征。


让我们从政治倾向开始。你可以重新浏览这篇文章的顶部来提醒自己我们是如何收集有关媒体的政治倾向的信息的。下面的代码使用一个字典来根据收集到的信息为每个发布名称分配left、right和center值。



我们再次使用groupby()来查找每个政治分组中气候变化文章的比例。



让我们看看每组中有多少篇文章,并对其绘制图表:


从上面的图表中可以明显看出,不同的政治倾向分组中气候变化相关文章所占的比例是不同的,但是让我们来正式检验一下我们的假设。为此,对于给定的一对文章分组,我们先提出零假设,即假设与气候相关的文章的总体比例没有差异。我们也为我们的校验建立一个95%的置信水平。


一旦我们收集了统计数据,我们就可以使用P值或置信区间来确定我们的结果是否具有统计意义。这里我们使用置信区间,因为我们感兴趣的是这个差值在什么范围可能反映总体比例的差异。我们对假设检验感兴趣的统计量是两个样本中气候变化文章所占总体比例的差异。回忆一下,置信区间和显著性检验之间有密切的关系。具体来说,如果一个统计量在0.05水平上显著不同于零,则95%置信区间将不包含0。


换句话说,如果0在我们计算的置信区间内,那么我们就不会拒绝零假设。但如果不在,我们就可以说相关文章的比例差异具有统计学意义。我想借此机会指出置信区间中一个常见的误解:95%区间给出了一个区域,如果我们重新采样,那么在95%的情况下,该区间将包含真实的(总体)比例差异。并不是说95%的样本都在该区间内。


为了计算该置信区间,我们需要一个点估计和一个误差范围; 后者由临界值乘以标准误差组成。对于比例差异,我们对它的点估计值是p 1- p2,其中p1和p2是我们的两个样本比例。在95% 的CI下,临界值是1.96。接下来,我们的标准误差是:


 

最后,置信区间是 (点估计 ± 临界值 X 标准误差), 或者:


 

我们使用一些辅助函数来把我们的数字代入这些公式。



最后,calc_ci_range函数会将所有内容整合在一起。



我们来计算一下倾向分组的置信区间,先看看“左”相对于“右”。



查看“左”相对于“右”出版物的比例差异,可以看到,我们的置信区间在1.8%到2.1%之间。这是一个相当窄的范围,并且相对于总体比例差异范围来说,也远远地远离零。拒绝零假设是显而易见的。同样,center对left的范围是1.3%到2.1%:




Because the assignment of publications to bias slant is somewhat subjective,

由于对出版物的分配从偏差偏倚的角度来看是有点主观的,这里有另一种变体,即将BusinessInsider、NYPost和NPR放入center中。



接下来,我们可以使用相同的方法查看出版物的所有权。我们将我们的总体样本分为四组,LLC(有限责任公司),corporation(有限公司),非营利组织和私人。



现在让我们来对该数据绘制图表,看看不同类型的公司是否以不同的比例报导气候变化。



或许结果一点也不意外,私营媒体和非营利媒体对气候变化的报导似乎比有限公司和有限责任公司要多一些。但我们来更仔细地看看前两个公司,即有限责任公司和有限公司在比例上的差异:



这里,置信区间是0.3%到0.7%,比之前的差异更接近于0,但仍然不包括0。我们可以预计从非盈利媒体到有限责任公司的区间也不包括零:



非营利媒体到有限责任公司的置信区间为0.6%至1.2%。最后,看看私人媒体相对于非盈利媒体的情况,我们发现置信区间是-0.3%到0.5%:



因此,在这种情况下,我们可以得出结论,在与气候变化相关的文章中,这两个总体的比例没有显著差异,不像我们比较过的其他总体。


总结: 进行文本分析来检验一个假设


在这篇文章中,我们对一个大型的新闻文章语料库进行了一些文本分析,并检验了关于它们内容差异的一些假设。具体来说,使用一个95%的置信区间,我们估计了不同新闻来源之间关于气候变化讨论的差异。


我们发现了一些有趣的差异,这些差异是统计显著性的,包括右倾新闻来源对气候变化的报道更少,有限公司和有限责任公司对气候变化的报道比非盈利媒体和私人媒体更少。


然而,就处理这个语料库而言,我们接触的只是冰山一角。你可以尝试使用这些数据进行许多有趣的分析,因此你可以自己从Kaggle下载这些数据并开始编写你自己的文本分析项目!


延伸阅读


Olteanu, A, et al. “比较在线新闻和社交媒体的事件报道:气候变化的案例”,第九届国际AAAI网络与社交媒体会议论文集(2015)。



英文原文:https://www.dataquest.io/blog/tutorial-text-analysis-python-test-hypothesis/ 
译者:忧郁的红秋裤
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/36040
 
294 次点击