用 R: 10 日常习惯用法处理缺失数据
r 提示
你应该把命令自动化
数据清理是数据分析过程中最耗时的阶段之一。它的许多步骤包括熟悉数据集、搜索缺失值、插补或删除缺失值,以及可能对不同变量或其组合的相同代码行进行大量重复。因此,我们必须寻找并接受任何加快进程的可能性。
不久前,我提交了一篇关于针对数据集中缺失值的简短 Python 习惯用法的文章。今天,我准备了类似的脚本汇编,但在 R 语言。此外,我们将再次使用 Kaggle 的葡萄酒评论数据集。
0.使用 NAs 打开数据集
是的,R 中的向量从 1 开始,但是在处理缺失值之前,我们应该有一个包含缺失值的数据集。有时,空记录会被替换字符串填充,如空格(“ “
)、“empty”
、“nan”
或一些垃圾。为了开始这项工作,我们应该用“真实的”NA
值来代替它们。幸运的是,我们可以在数据集开放阶段做到这一点:
wine_data <- read.csv(‘winemag-data-130k-v2.csv’,
**na.string** = c(‘’, ‘i’, ‘P’))
na.string
接受替代值的向量。
1.有没有完全缺失的值?
开始时,我们需要检查缺失值的存在。我们有is.na()
用于这些目的。它接收数据并返回一个布尔向量。
- 检查是否缺少单个值:
is.na(wine_data$region_1[2])
- 获取某些列中缺少元素的行:
wine_data[is.na(wine_data$country),]
- 检查一列中是否有缺失值:
all(!is.na(wine_data$points))
- 检查一列中是否有缺失值:
any(is.na(wine_data$country))
2.检查缺失值存在的最短方法
以前的脚本需要一些关于数据集的知识和对独立元素的访问。但是如果我们想看到全貌呢?答案是na.fail()
功能。如果整个数据中有任何缺失值,它将引发异常:
na.fail(wine_data)
3.了解整体情况
有一个特殊的函数,替代了一堆过滤器和索引。它主要用于数据框,可用于显示所有缺失值的行(在任何列中):complete.cases()
。它返回一个布尔向量,非常方便索引。
- 获取缺失数据的行数
sum(!complete.cases(wine_data))
- 获取有缺失数据的行
wine_data[!complete.cases(wine_data), ]
4.更实用的命令
所有以前的脚本主要用于探索性任务:展示、获取等…但是如果我们需要得到缺失值的索引呢?在这种情况下,我们应该使用which()
功能:
which(is.na(wine_data$country))
#returns indexes of rows with missing data
5.NA 值的高级使用
看来,NA
价值观存在的唯一目的就是被清除。不过,我们可能会在一些非常有趣的组合中使用它们。例如,我们有一个混合数据向量:
test_vec <- c( 'ten', '5', 'n', '25', '10')
我们希望将“可转换”的字符串(如‘5’
或‘25’
)与其他字符串分开。我们可以和is.na()
功能一起做:
test_vec[!is.na(as.numeric(test_vec))]
# returns ( '5', '25', '10' )
6.跳过 NAs 进行计算
NAs
存在有一些副作用——它把几乎任何操作的结果值都变成了NA
。但是有一个解决方案——很多 R 函数都有内置的na.rm
参数,允许跳过缺失值。
mean(wine_data$price)
# returns NAmean(wine_data$price, **na.rm** = T)
# returns the result
7.忽略数据集中所有缺失的值
你可以看一下以前的脚本,然后想,省略丢失的值是一件非常乏味的工作。嗯,是的,它是。但是如果需要一次删除所有的NA
并把它们当作一场噩梦忘记,R 为我们提供了以下功能:
wine_data_totally_cleared_1 <- na.omit(wine_data)wine_data_totally_cleared_2 <- wine_data[complete.cases(wine_data),]
如你所见,我们可以使用已知的特殊功能na.omit()``complete.cases()
。结果是一样的:数据集中不再有缺失值。
8.省略数据集中一些缺失的值
当我们构建一些过滤器时,我们希望结果只有匹配的值。在处理数据框时,它变得尤其有价值。但是,如果您运行以下命令:
wine_data_condition_NA <- wine_data[wine_data$price > 20,]
您不仅会得到正确的子集,还会得到所有缺失的值。它是 R 数据帧索引、布尔数组和NA
性质的结果:缺少值将条件结果变成被视为非FALSE
的NA
。我们仍然有丢失值搜索的痛苦。
解决方法是subset()
功能:
wine_data_condition <- **subset**(wine_data, wine_data$price > 20)
它返回正确的子集,但没有 NAs,NAs 被过滤掉了。
9.关于缺失值的更多信息
让我们回到查看数据集全貌时的步骤。我们希望看到缺失值的分布,也许是一些模式,或者变量之间的依赖关系。我们还有另一个具有所需功能的 R 包— “鼠标”包。它包含一些函数,这些函数遍历数据集,统计所有的遗漏,并构建数据集的图片。举个例子,我们来举个例子:wine_data[1:5, 4:8]
。它包含下一个数据:
正如我们看到的,有一些丢失的值。让我们应用上述包中的 md.pattern()函数:
require(mice)
md.pattern(wine_data[1:5, 4:8], plot = F)
我们得到了模式表:
最左边的索引显示行数。最右边的索引显示缺失特征的数量。中间的矩阵显示了模式:在计算的行中缺少哪个特征组合。所以第一行告诉我们,有 2 行没有缺失数据(0 个缺失特征)。第三行显示,数据片段中有一行缺少一个特征,即缺少price
。
10.形象化
现在我们准备好可视化缺失值的分布。我们为这项工作准备了另一个 R 包— VIM 库。在许多其他函数中,它绘制空记录的分布直方图,并根据上一步构建模式表的可视化表示:
require(VIM)
aggr_plot <- aggr(wine_data, col=c(‘navyblue’,’red’),
numbers=TRUE, labels=colnames(wine_data),
ylab=c(“Histogram of missing data”,”Pattern”))
我们有一幅美丽的图画:
例如,现在我们可以看到,几乎 60%的行没有region_2
值。
对于我来说,你应该把这些代码片段自动化。你会收集到超速行驶的重要分析。此外,和往常一样,您可以在我的 GitHub 上找到带有工作示例的代码:
为中型文章构建的代码和模型示例- Midvel/medium_jupyter_notes
github.com](https://github.com/Midvel/medium_jupyter_notes/blob/master/r_missing_values/missing-values.R)
请确保您已经看过我之前关于 Python 习惯用法的文章:
[## 每个数据科学家都应该知道的获取缺失值的 7 个习惯用法
你应该把命令自动化
towardsdatascience.com](/7-idioms-to-acquire-missing-values-every-data-scientist-should-know-2edf4224360c)
在制造业中处理批量生产数据
解决两个常见问题:验证和模型训练
埃文·德沃金在 Unsplash 上拍摄的照片
很多制造业的生产过程都是分批完成的。一个批次中的两个项目以相同的生产设置生产。因此,这两件物品要么是完全相同的复制品,要么是非常相似的复制品——一件**伪复制品。**伪重复是指属性非常相似,甚至在某些情况下完全相同的项目。
这种批处理过程加快并简化了生产流程。然而,如果你在这样的环境中工作,并且想要使用数据科学和机器学习来通知你的决策,你需要非常小心如何使用你的数据。
当考虑将机器学习应用于批量制造数据时,会出现两个主要挑战。第一是确保您正确地验证了您的模型,第二是使用批量数据处理实际的模型训练。
让我们依次看一看每一个,并给你一些如何解释这些问题的想法。
第一步——修正你的验证
批量数据的最大问题是验证。最常见的验证方案——交叉验证、分割验证和引导验证——假设你的每一个例子都是独立的。
但是如果你批量生产,情况就不一样了。
让我们来看看,即使您的观察结果并不相互独立,您如何仍然能够验证您的模型。请记住,验证是数据科学家相信他们的分析的主要原因。这就是为什么把这件事做好是至关重要的。
要在批量生产环境中做到这一点,我们需要确保来自一个批次的所有示例总是在我们进行的任何数据验证分割的训练或测试端。
如果我们不这样做,我们正在训练的模型基本上就能够作弊——它会知道一些测试行的正确答案,因为在训练数据中存在一个相同(或非常相似)的行。因此,验证过程会说模型是好的,但是一旦它投入生产并且不能再欺骗了,它的性能就会下降,很可能下降很多。
在 RapidMiner 中,这可以使用交叉验证操作符的“批量属性分割”选项来完成。如果选中,所提供的示例集需要包含一个批处理属性,以便该操作符进行操作。本字段手动定义属于一个批次(或一次交叉验证)的内容。
上面描述了一种派生 BatchId 属性的常见解决方案。这里,modulo 函数用于从数字 Id 生成 BatchId,在本例中,数字 ID 是一个商品 ID。mod 函数计算除法的余数,因此 mod(11,10)返回 11 除以 10 的余数。答案就是你在这里看到的 1。
使用这个选项,我们防止一个出现项 11 出现在训练集中,而另一个出现在测试集中。
如果您使用的是拆分验证而不是交叉验证,您可以通过首先使用排序运算符按 ID 列排序,然后使用筛选示例范围来解决这个问题。这将数据集分成两部分。但是这一次不是随机抽样,因为在分割之前已经按照 ID 进行了排序,所以相关的项目在数据集中并不相邻。
完成此操作后,您可以使用前 x 行训练,剩余的 y 行可用于测试,因为训练部分现在不同于测试部分。(由于数据量较小,在分割数据时数据集之间少量溢出的可能性通常可以忽略。)
既然我们已经处理了验证,我们需要解决批量数据可能存在的潜在混乱
第二步—处理数据本身
在普通学习者中使用您的数据可能会对模型造成一些混淆。请记住,由于数据的分批性质,您的学习者可能会遇到 10 个项目,其中只有一个是“正确的”,即使它们彼此非常相似。
根据您的算法,这可能会对您的模型最终的工作方式产生严重的影响。
因为学习者通常偏向于在他们不确定的情况下预测大多数,所以输入大量非常相似的数据点可能会使模型偏向这个方向。
对于基于树的算法,您必须修改您的修剪策略,因为在考虑批量数据时,类似“如果样本少于四个,则不要分割这个分支”这样的设置可能不合适。
因此,在模型训练过程中以特殊方式处理批数据可能是有意义的。以下是如何在模型训练过程中克服批量数据挑战的三种方法。
1.抽样
正如机器学习中经常出现的情况,解决问题的方法之一是使用采样方法。我们可以从批处理过程中随机抽取一个项目,并将其用于模型训练和测试。这很好地解决了分类问题中保持类别平衡的问题,以及回归问题中的标签分布问题。
这也是一个简单的技术。缺点是您会丢失示例,因此也可能会丢失信息。这实际上取决于是否通过使用给定批次中的多个项目获得了额外的信息。
可能会有,因为每个单独的项目可能是用相同的材料制作的,只有生产设置不同。但是,从每一批中包含一个以上的项目示例可能也不会有什么收获——这是您必须根据您的特定用例来决定的事情。
2.权衡和改变问题
就像不平衡分类问题一样,您也可以在这里使用一种加权技术来克服这个问题。您不需要删除示例,而是对单个批次中的项目进行平均,并将行数作为您的学员和表现的权重。
这对于所有的学习者来说是不可能的,但是相当多的普通人支持它。为了弄清楚你的学习者是否支持它,你可以右击一个操作符并说看看操作符信息。
当然,这种策略也有一些缺点。
首先,平均你的所有属性可能不是最好的办法。如果你的值相差很大,那么当你取平均值时,你又会丢失很多信息。这又可以归结为这些问题:你的行有多少是重复的?它们只是依赖的伪副本还是真副本?
手头的另一个问题是如何处理标签?对于回归问题,例如测量的浓度,当然可以取平均值。但这是你需要的吗?你对最大值更感兴趣吗?还是第八届十周年?与往常一样,您应该让您的数据科学方法与手头的业务需求保持一致,并仔细考虑您正在做出的选择。
对于分类问题,您会遇到模式(最频繁的类别)可能更不适合的问题。在这种情况下,分类问题通常是真正的挑战,当你问一些东西是否通过了质量测试。
在这里,你可以使用旧的计算机科学技巧,改变问题。你可以考虑从基于项目的问题转移到基于批量的问题。你可以回答的问题是:我的批次中有多少部分不能通过质量测试?
这是一个批量级的回归问题,如果需要可以转化为分类问题。
3.组装
解决批量问题的一个有趣的方法是使用抽样方法,但是使用集合方法。这个想法是你建立多个学习者。每个学员只能看到给定批次中的一个项目。
这个项目是随机选择的。多次这样做可以确保您不会丢失信息。这个想法可以被认为是一个随机森林,其中随机抽样被分层抽样所取代。
4.就让它保持原样
在谈了一些先进的想法之后,我想强调的是,仅仅“按原样”使用数据也是一个有效的选择。
机器学习算法被设计为鲁棒系统。他们习惯于在噪音中工作。因此,原则上他们也可以使用这些伪副本。
随机森林甚至在它们的引导抽样中有意产生相似的副本。因为随机森林是非常健壮的学习者,并且引导是随机过程,所以这不会损害森林。
最后的想法
和机器学习一样,没有免费的午餐,也没有简单的答案。上面列出的想法是坚实的起点。然而,您真正知道什么最适合您的数据的唯一方法是尝试一些事情,看看什么最适合。
记住,模型训练本质上是一个迭代的过程,所以看看什么最适合你的特定用例。
机器学习项目人类指南
启动机器学习项目很难。这个问题的解决方案是从一开始就建立一个坚实的项目基础,为自己的成功做准备。我在本指南中概述的流程将有助于简化这一过程。
【rapidminer.com】这篇博文最早发表于 博客 。
在 Python 上处理大量石油测井数据并提高时间效率
Python 如何彻底改变了我们与石油行业大数据的交互方式,我们应该了解它吗
地球的一部分。图由Ani-Mate/shutterstock . com 提供
T 这是一个地球物理学家的故事,他已经厌倦了在大多数商业软件中用手工输入来处理大量的测井数据。谁和我有同样的感觉?然而,我成功地开发了一种方法,几乎不用 Python 编程技巧就能摆脱这种累人的手工输入。在这里我想和你分享一个教程。我假设你熟悉地质学、地球物理学、石油工程以及所有与地球科学相关的东西。然而,如果你不熟悉它,没关系,我很高兴向你介绍我们正在处理的日常活动。老实说,对于开源计算来说,Python 是一种非常灵活但非常强大的语言。
测井数据看起来是这样的!乱七八糟但是油油的有营养。 (Aliouane 等人,2012 年)
在石油工业中,测井数据是一种非常有价值的数据来源,用于解释地球深处的地下图像,并获得更多关于岩石内部的信息:如果你足够幸运,你会发现石油。反正开玩笑!寻找石油的事业花了很多年。关键是,时效。时间效率,主要是在探索阶段,对企业的未来意义重大。当一个油田已经生产了几十年的时候,测井数据从来不会以单一或少量的形式出现。可以是 50 口,100 口,甚至 500 口油气井。这肯定是非常巨大的,因为已经钻了很多井。一个测井数据包含岩石的测量数据,例如密度、声速、伽马射线、电阻率等等。因此,总共 46 个井的大量数据可能占用大约 120 MB!测井数据通常采用 LAS 格式(我将在本教程中完全使用这种格式)。
LAS 数据中的测井数据示例
就我个人而言,迄今为止我所知道的大多数商业软件都有时间效率限制,因为我们必须重复地手动输入关于我们输入的每个测井数据的所有详细信息。如果我们有大量数据,这可能会很乏味和麻烦。
想象一下,光是手工输入和检查数据的单位,我们就要花费多少时间!然后我发现使用 Python 非常吸引人!
辅导的
打开你的 Python,先导入 Python 库的“三剑客”; numpy , matplotlib ,以及 熊猫 。我之所以称他们为“三剑客”是因为他们不能独立工作,因为 Python 中的任何基本计算都需要 numpy 和 matplotlib ,以及数据需求 pandas 。
import numpy as npimport matplotlib.pyplot as pltimport pandas as pd
现在进入包含 LAS 格式的多井测井数据的文件夹。复制文件夹的路径,用 Python 指定路径,将路径粘贴在上面。
import syssys.path.append('...')
现在是有趣的部分!你会看到所有的文件。导入 glob 并导入文件。
import globimport os file_path = "/content/drive/My Drive/Colab Notebooks/well_logs"read_files = glob.glob(os.path.join(file_path, "*.las"))read_files
如果成功,将出现您的多条测井数据的路径和文件名。如果你读取 100 个测井数据,它将显示为一个很长的列表!
Glob 成功读取您的数据
由于您只对文件名**(无文件夹路径)感兴趣,即井名,例如从上面的例子中,只对**660810-B-1BH**
感兴趣,而不是对整个**/content/drive/My Drive/Colab Notebooks/well_logs/660810-B-1BH.las**
感兴趣,您可以将不需要的文件路径名分类出来,这样您将只得到井名。**
well_names = []for files in read_files: files = os.path.splitext(os.path.basename(files))[0] well_names.append(files)print(well_names)
这将为您提供油井名称
井名
调查你有多少数据。
print(len(well_names))
例如,你有 45 口井的数据。由于 Python 从 0 开始索引,而不是从 1 开始索引,这意味着第一口井名 660810-B-1BH
和最后一口井,分别被:
print(well_names[0])
print(well_names[44]) # 45 wells minus one
在 Python 和任何编程语言中,你几乎总是通过索引来调用一些东西。
Python 索引的公式永远是:从零开始,某物减一。
现在您已经有了井名,是时候读取所有 LAS 数据了。你将使用一个非常专用的库来读取 LAS 文件,名为 lasio 。Lasio 是一个可以读取 LAS 文件的优秀库,事实上你也可以自己从头开始构建一个程序!不过 lasio 对于时效来说已经足够了。这是我想强调的最重要的一点,即您可以同时导入所有文件,甚至一次点击 100 个文件,这是使用一些商业软件几乎无法做到的。在导入过程中,你不需要专注于手动检查和输入合适的单位。表演时间到了!
先安装 拉索T22。我假设您可能已经非常熟悉如何安装库了。您可以编写一点儿代码pip install
,或者更容易的是,您可以浏览这些库并将其导入到一个名为 PyCharm 的 Python IDE 中。
pip install lasio
安装成功后,导入它,只用写 4 行代码就可以用 lasio 读取 LAS 文件。但是你必须有耐心,因为这需要相对较长的时间。所花费的时间取决于你导入的测井数据量,然而估计读取 50 条测井数据不会超过 30 秒。
lases = []for files in read_files: las = lasio.read(files) lases.append(las)
导入过程与从头到尾读取井名的顺序相同。在导入过程中,您可能会遇到一条警告,内容如下:
这是对 OK 的警告
以我的经验来看,很正常,所以一切都没问题。
恭喜你!您在总共不到 5 分钟的时间内导入了大量测井数据。
是时候看看你的数据是什么样子了。请记住,在我们之前的讨论中,井名可以通过索引来调用。例如,我们称为索引 19 。
# type the numbers from 0 to max number of wells in the wellnames[...]find = well_names[19]# print the name of the searched wellprint("Well name:", find)
如果调用索引 19,它将打印第 20 个井的名称。请再次记住上面的经验法则:指数是某个东西减一。
上面的代码工作起来就像一个目录。现在编写下面的代码,看看第 20 个测井数据里面有什么。
id_ = np.int64(np.where(wellnames==find)).item()print("Data available:", lases[id_].keys())# check more detailsprint("Detail about data:")print(lases[id_].curves)
它将打印两件事:测井记录中的可用测量数据和测井记录数据的详细信息。****
可用数据的打印输出
它告诉你什么数据是可用的。这里可用的数据有:深度、TVD、TVDSS、GR、KLOGH、NPHI、PHIF、RHOB、SW 和 VSH 。这些是什么?这些是岩石测量类型的首字母缩写词(或所谓的助记符**,例如 GR 代表伽马射线, KLOGH 代表渗透率, NPHI 代表中子孔隙度, RHOB 代表密度,以及 SW 代表水饱和度。每个测量值都有特定的单位,你必须注意。**
这条信息非常重要,比内容本身重要得多。这条信息就是我们在文件头中看到的。
现在终于到了我们教程的最后一部分。我们非常希望看到测井记录。在 data_view
变量中输入所需的测量类型。例如,我们有兴趣查看密度日志或 RHOB 数据。输入RHOB
。我们将使用 matplotlib 。
# peek or overviewing the well log# which data you want to see??? data_view = 'RHOB' # input the measurement type which data you want
# to seeprint("Data", data_view, "of well:", find)plt.figure(figsize=(5,10))plt.plot((lases[id_][data_view]), (lases[id_]['DEPTH']))plt.xlabel(data_view); plt.ylabel("Depth (m)")plt.grid(True)plt.gca().invert_yaxis()
可视化只是打印出以下内容:
密度测井可视化
恭喜,我们的教程到此结束!
如果你仍然渴望以上测井数据的更漂亮的可视化**,我有一个绝妙的配方!**
但是因为这篇教程没有涉及到这个问题,所以我会把它留到以后,如果你渴望的话,我会写另一篇教程。
你学到了什么?
首先,你已经学会了如何导入多个测井数据文件;** 50,100,200 档,或更多**,不超过 5 分钟。你已经打破了在商业软件中手工输入的平均时间。其次,你已经学会了如何通过索引数据对文件进行分类。有 50 个、100 个、200 个井名,你肯定不想一一点名,因此索引是一个更好的方法。最后但同样重要的是,你已经学会了如何打印出数据的细节(标题)和可视化数据**。**
从长远来看,我只能说 Python 在处理大数据方面非常惊人,超过了普通软件处理相同数量数据的平均时间。如果你觉得你可以通过编写更高效的代码及时击败我,请联系我并告诉我!
到达我的 GitHub:github.com/yohanesnuwara
到达我的邮箱:ign.nuwara97@gmail.com
到达我的 LinkedIn:【https://www.linkedin.com/in/yohanes-nuwara-5492b4118/】T42
处理 Power BI 中的空白
如何应对 Power BI 报表中的空白值?检查这三种可能的解决方案
皮查拜在 Pexels.com 拍摄的照片
在创建报告时,我敢肯定,当您最终得到“(空白)”时,您会面临这样的情况,并且您不希望像这样显示给您的最终用户。当然,在某些情况下保留空白是有意义的,但最常见的情况是您想要显示其他内容而不是它(对于数字来说是 0,对于文本来说可能是‘N/A’或‘Unknown’)。
可能的解决方案
那么,在 Power BI 中有哪些处理空白的选项呢?我们直接在那里查吧…
我会用 Stack Overflow 2013 数据库。这个数据库包含了超过 2000 万条记录的表,所以如果要衡量性能,绝对比玩 Adventure Works 或者类似的数据库要好。
比方说,我想看看每一年有多少评论。首先,由于数据库中没有具体的年份值,我需要使用以下公式创建一个计算列 Year Comment :
Year Comment = YEAR(Comments[CreationDate])
下一步是创建一个衡量所有评论的标准。
Total Comments = COUNT(Comments[Id])
在这里,我们得到了每年的评论总数。现在,假设我们要专门计算 2012 年还剩多少评论。这可以用许多不同的方法来实现,但是我使用下面的公式:
Comments 2012 =
CALCULATE (
COUNT ( Comments[Id] ),
FILTER ( Comments, Comments[Year Comment] = 2012 )
)
让我暂停一下,给你介绍一下 DAX 工作室。也许你们中的一些人对这个工具很熟悉,但是如果你经常写 DAX 并且每天都使用 Power BI,这个工具是必须的!我不会详细说明它提供了什么功能——我会诚实地说它很棒,也是最重要的——它是完全免费的!所以,马上去下载 DAX Studio 吧:)…
我将使用 DAX Studio 来测量我的视觉效果的性能。让我们连接我们的。pbix 文件,并将我们新创建的度量添加到报告中。
我还打开了 Power BI 中 View 选项卡下的 Performance Analyzer,以便捕捉将在后台执行的查询。下面是 BI 生成的显示我们想要的内容的查询:
// DAX Query
EVALUATE
TOPN(
502,
SUMMARIZECOLUMNS(
ROLLUPADDISSUBTOTAL('Comments'[Year Comment], "IsGrandTotalRowTotal"),
"Total_Comments", 'Comments'[Total Comments],
"Comments_2012", 'Comments'[Comments 2012]
),
[IsGrandTotalRowTotal],
0,
'Comments'[Year Comment],
1
)
ORDER BY
[IsGrandTotalRowTotal] DESC, 'Comments'[Year Comment]
现在,让我停下来,试着解释一下背景中发生了什么。当您在 Power BI 中与可视化交互时,每次都会生成查询并将其发送到 Analysis Services (Tabular)引擎(Vertipaq),该引擎在后台运行并执行“脏”工作。
在下图中,我们可以看到 Vertipaq 是如何处理这个查询的:
解决方案 1:使用 IF
现在,我们开始处理视觉中的空白值。第一种情况是最明显的,我想也是最常用的。解决空白的措施如下:
Blank v1 comments =
IF (
ISBLANK (
CALCULATE (
COUNT ( Comments[Id] ),
FILTER ( Comments, Comments[Year Comment] = 2012 )
)
),
0,
[Total Comments]
)
并且,我们得到以下结果:
所以,我们在这里:我们显示的不是空白,而是零。让我们检查一下这个查询是如何执行的:
当然,对于简单的度量,差异不是很大,但是对于复杂的 DAX 和不同的过滤上下文,在数百万行的表上,差异可能很大。
解决方案 2: COALESCE()
最近 Power BI 推出了一个全新的功能:COALESCE()。对于那些来自 SQL 世界的人来说,这是一个众所周知的函数,但是让我为那些不熟悉它的人简单解释一下。基本上, COALESCE 将遍历作为参数传递的值,并返回第一个非空值(在 SQL 中不是 null)。
聚结(列 1,列 2,列 3…列 N)
因此,COALESCE 将检查列 1,如果值为空,它将检查列 2 的值。如果它也是空的,它将继续,直到找到第一个非空值。作为最后一个参数,您应该指定在所有检查的参数都返回空白时要返回的值,如下所示:
COALESCE(column1,column2,column3…columnN,0)
让我们使用 COALESCE 函数为我们的报告创建一个度量:
Blank v2 Comments coal =
COALESCE (
CALCULATE (
COUNT ( Comments[Id] ),
FILTER ( Comments, Comments[Year Comment] = 2012 )
),
0
)
结果完全相同:
让我们检查一下这种方法的性能:
解决方案#3 技巧用 0
这是我看到王九思用过的一个小技巧。对于那些不知道的人来说,Jeffrey Wang 是 DAX 最知名的名字之一。
有什么诀窍?在 DAX 中,空白+ 0 就是 0!是的,我知道,对于我们这些来自 SQL 环境的人来说,他们认为 blank 是 SQL 的空孪生兄弟,这是完全出乎意料的行为。尝试在 SQL Server Management Studio 中运行以下命令:
select NULL+0
正如您所想,结果是空的。在 SQL 中,NULL+something 总是 NULL…在 DAX 中,它不是:)
因此,让我们在报告中尝试这个解决方案:
Blank v3 Comments 0 =
CALCULATE (
COUNT ( Comments[Id] ),
FILTER ( Comments, Comments[Year Comment] = 2012 )
) + 0
结果还是完全一样:
最后,我们来看看后台发生了什么:
没那么差哈:)
结论
如您所见,在 DAX 中有多种处理空白值的方式。根据数据集的具体特征,您应该测试不同的可能性,并选择最适合您需求的一个。
感谢阅读!
以正确的方式处理分类数据
最被低估的数据编码方式以及你做错了什么
分类数据只是聚合成组的信息,而不是数字格式,如性别、性别或教育 水平。它们存在于几乎所有现实生活的数据集中,然而当前的算法仍然难以处理它们。
以 XGBoost 或大多数 SKlearn 模型为例。如果你试图用分类数据训练它们,你会立刻得到一个错误。
目前,许多资源宣传了各种各样的解决方案,这些解决方案起初看起来可能有效,但一旦仔细思考,就会发现它们大错特错。对于非有序分类数据来说尤其如此,这意味着这些类是无序的(可能是 Good=0,Better=1,Best=2)。区分数据科学家应该使用的方法和那些只是让模型运行的方法需要一点清晰。
不要做什么:标签编码
最简单和最常见的转换分类变量的解决方案之一是标签编码。它包括用相应的编号替换每个组,并在整个特征中保持这样的编号一致。
标签编码的例子
该解决方案使模型运行,并且是有抱负的数据科学家最常用的方法之一。然而,它的简单性带来了许多问题。
距离和顺序
数字维系关系。例如,四是二的两倍,当直接将类别转换为数字时,尽管原始类别之间不存在这些关系,但它们还是会被创建。看前面的例子,英国变成了法国的两倍,法国加美国等于德国。
嗯,这不完全正确…
这对于算法来说尤其是个问题,例如 K-Means,在运行模型时会计算距离度量。
解决方法
一键编码
一键编码是处理非有序分类数据的最常见、最正确的方法。它包括为每组分类特征创建一个附加特征,并标记属于(值=1)或不属于(值=0)该组的每个观察值。
独热编码的例子
这种方法能够正确地编码分类特征,尽管有一些小缺点。具体来说,大量二进制值的存在对于基于距离的算法(如聚类模型)来说并不理想。此外,大量额外生成的特征引入了维数灾难。这意味着由于数据集现在的高维数,数据集变得更加稀疏。换句话说,在机器学习问题中,每个特征组合至少需要几个样本。增加特征的数量意味着我们可能会遇到对每个特征组合没有足够观察值的情况。
目标编码
一种鲜为人知但非常有效的处理分类变量的方法是目标编码。它包括用目标变量中的平均响应替换分类特征中的每个组。
目标编码的示例
获得目标编码的过程相对简单,可以概括为:
- 按类别对数据进行分组
- 计算每组目标变量的平均值
- 将平均值分配给属于该组的每个观察值
这可以通过几行代码实现:
encodings = data.groupby('Country')['Target Variable'].mean().reset_index()data = data.merge(encodings, how='left', on='Country')data.drop('Country', axis=1, inplace=True)
或者,我们也可以使用 category_encoders 库来使用 TargetEncoder 功能。
目标编码也是一种强大的解决方案,因为它避免了生成大量的要素,就像一键编码一样,保持了数据集的原始维度。
摘要
处理分类特征是数据科学家的一项常见任务,但是,人们通常并不确切知道正确处理它们的最佳实践是什么。
对于非顺序类别,标签编码,包括用一个相对随机的整数替换一个类别,应该不惜一切代价避免。
相反,一键编码和目标编码是更好的解决方案。一键编码可能是最常见的解决方案,在现实生活中表现良好。目标编码是一种鲜为人知但很有前景的技术,它也可以保持数据集的维度一致,从而提高性能。
阅读更多类似的文章,请关注我的Twitter,LinkedIn或我的 网站 。
最小化新冠肺炎对数据科学影响的三大方法(第 1 部分)
减轻或解释数据中新冠肺炎效应的方法。
凯文拍摄的照片:Unsplash
在试图回答“ 为什么 ”关于新冠肺炎对数据科学的影响的问题后,有必要继续讨论“ 如何处理 ”的问题。本系列旨在利用行业数据科学领导者的意见,为“”提供一些潜在的答案。
不确定“为什么”是什么?你可能没看过这个系列的前奏。请在这里阅读以了解新冠肺炎对数据科学方法可能产生的影响,然后再进一步。
到目前为止,在这个系列中,我们将回顾丢弃数据、替换数据和特征工程方法。在第一部分中,我们将了解删除数据和替换数据。
最后,我要特别感谢本系列的合著者 Renee Ernst,General Mills 的资深首席数据科学家,她凭借自己在食品行业的经验成为了宝贵的信息来源。
简介
快速回顾一下!
在过去的 2-3 个月里,数据集被新冠肺炎效应弄得乱七八糟。在许多情况下,流入的数据并不反映正常的行为或情况。与更典型的异常值不同,这些数据是一些数据集的相当大的一部分,因此,传统的异常值补救措施可能无法帮助解决由这些异常数据引起的问题。这种“不正常”的数据也可能会持续流入一段时间,直到我们回到正常状态。在这次讨论中,我们只关注如何确保我们的模型在我们回归常态后能够继续很好地预测,而不是试图预测新冠肺炎本身的影响或轨迹。
图片来自坦布
对于预测模型,数据科学的假设“垃圾数据输入,垃圾数据输出”仍然非常重要。虽然我们试图讨论一些方法来建立稳健的模型,以最小化或考虑新冠肺炎的影响,但这些方法不能神奇地使你的预测模型准确,可能有其他方法在不同的情况下更好地工作。我们每个人都在一个独特的空间中工作,因此我们在处理这些数据时所做的基本假设需要有所不同。这些假设会因行业和使用情形而异,并且需要处理和更改数据,而在正常情况下,我们会尽力避免这种情况。我们需要坦率地说出我们的选择、做出这些选择的原因以及对我们模型的影响。
用谷歌首席数据科学家凯西·科兹尔科夫的话说,“在你写的每一行都要多次乞求原谅。
丢弃数据
这个方法很简单,但是也是最假设的!想法是丢弃或替换对预测模型有不利影响的“异常”COVID 数据。这似乎是一个简单而诱人的解决方法,但是这些方法都有其局限性。为了使这些方法起作用,我们将对数据进行大量假设,包括对丢弃/替换数据的预测能力的假设。丢弃方法的最大问题之一是它在处理相对少量的数据时的影响,尤其是当它需要丢弃大量数据时。
随着与 COVID 的斗争愈演愈烈,它继续蔓延到我们生活的方方面面。不管怎样,它正在影响我们的日常生活。尽管这可能不是“常态”,但在未来,我们还不确定何时会达到新常态,或者新常态会是什么样子。我们在此次危机最严重时期收集的数据仍有可能为我们提供未来将如何受到影响的重要见解。假设这些数据与未来无关,从而完全忽略这些数据,这可能是幼稚的。然而,如果我们可以确信在新冠肺炎期间收集的数据不会以任何方式反映未来,并且我们有足够的数据在删除这些数据后仍然可以构建准确的模型,那么删除这些数据是一个合理而实用的解决方案。下降法可能有效的一个例子是预测(一旦事情恢复正常)期间的能源使用。给定时间内能源使用量的最佳预测指标之一是上一天或上一周同一时间的能源使用量。鉴于世界各地的许多企业和公共场所目前都处于关闭状态,如果不采取某种方式加以解决,最新数据将会失真,并将影响我们随后的预测。使用多变量建模仍有可能处理这些数据,这将在后面讨论,但另一种方法是丢弃最近的数据,并将新冠肺炎之前的数据视为最近的记录。
替换数据
当历史数据有限,但被替换的数据适用于所讨论的时期时,替换数据成为一种可行的方法,尽管是在某些假设下。
我们之前的能源预测示例可能是一个替换数据是更好选择的例子。假设由于历史数据有限,单独删除数据不是一种选择。我们可以用上一年同期的数据替换受影响的数据。这样做时,我们可以很容易地考虑到自去年以来能源使用的任何平均增加/减少,将一个因素应用到我们替换的数据,考虑到这种变化。替换方法是用这一时期(新冠肺炎撞击之前)的原始预测替换受新冠肺炎撞击的数据。如果去年的数据是陈旧的,这可能会有所帮助,如果我们在新冠肺炎之前对我们的模型的总体准确性非常有信心,这将是一个好方法。从上面的例子可以明显看出,被替换的数据需要在历史上是准确的。
另一种数据替换技术可能有用的情况是在预测历史数据有限的产品的销售时。例如,假设您预测每周的区域卫生纸销售量,但只有几年的数据。如果你想预测新冠肺炎危机(希望)过去后的未来销售,你需要一些方法来处理几个月的新冠肺炎数据。如果危机影响了 3-4 个月的销售,而您只有 3 年的数据,这已经影响了您 10%的数据,因此您可能不想丢弃它。相反,您可以用历史值替换数据,或者如果您的预测在过去非常准确,您可以用以前的预测数据替换它。当然,这是有风险的,但是只要用清晰的交流来详述这些风险,这可能是一个可行的解决方案。
关于作者
Usman Gohar 是一名数据科学家,明尼阿波利斯数据科学的共同组织者,也是一名技术演讲人。他非常热衷于最新的数据科学研究和机器学习。你可以在 LinkedIn 、 Twitter 、Mediumfollow onGithub上与他联系。
Renee Ernst 是 General Mills 的高级首席数据科学家,担任一个数据科学家团队的技术经理,该团队构建用于情景规划和优化促销的模型。工作之外,她还积极参与数据科学社区,包括共同组织即将举行的minne AnalyticsWomen in Analytics and Data Science conference 等活动。你可以在 LinkedIn 和&Github 上找到 Renee。
使用几何 SMOTE 处理不平衡数据
SMOTE 变体的几何方法
图 1 .作者随机生成的数据
在上面的图中,很明显,红色的点占多数,绿色的点占少数。少数数据的存在在异常检测、攻击和入侵检测、医学领域[癌症预测]和网络物理环境的研究中至关重要。但是数据样本中少数民族的数量是至关重要的。比方说,如果只有 0.01%的有用少数数据,通常算法会将其视为噪声或异常,并试图通过忽略这一点来提高准确性。如上所述,在许多情况下,不考虑少数群体数据样本比因其代表性不足而删除或忽略它们更为关键。
当类别样本的数量大致相等时,通常的机器学习算法工作得最好,并且通常朝着提高准确度和最小化误差的方向调整[1]
因此,基于这种说法,数据不平衡必须得到处理,因为当数据接近平衡时,算法会工作得更好,技术世界有许多方法来解决这一常见现象。
处理不平衡数据
我们可以通过算法和框架来解决不平衡数据的琐碎机器学习问题,这些算法和框架大致分为两个主要领域;预处理和代价敏感学习。重采样和特征选择是预处理方法的主要方式。
数据重采样:
这种方法修改了数据样本的数量,从而解决了偏斜类别分布或不平衡数据的不利影响。
- 过采样:过采样是添加少数类的更多副本。当您没有大量数据要处理时,过采样可能是一个不错的选择。但是过度的过采样可能会导致过度拟合。但是我们不会丢失有用的信息或特征。
- 欠采样:欠采样是去除多数类的副本。当有大量数据时,可以设计欠采样。但是这里主要关注的是我们删除了有价值的信息。这可能导致对测试集的拟合不足和泛化能力差。
- 混合:过采样和欠采样的适当混合。
- SMOTE:与过采样类似的技术,但这里我们合成新的少数数据样本。
重击
SMOTE 算法是由舒拉、鲍耶、霍尔和凯格尔迈耶在 2002 年提出的,作为随机过采样的替代方案。合成少数过采样技术(SMOTE)的思想是在相邻少数类实例之间进行插值。SMOTE 的任务是通过对数据进行随机重采样来克服过度拟合的问题,并继续协助泛化。SMOTE 能够通过在邻域中合成新的少数类样本来增加少数类实例的数量,从而帮助分类器提高泛化能力。
SMOTE 在少数实例之间生成新的少数样本。考虑两个少数点,算法沿着连接这些少数点的线生成新的少数样本。这是 SMOTE 算法的抽象视图。
k = nearest neighbours
n = no. of samples to be generated based on Imbalanced Ratio.
SMOTE 算法(k,n):
第一步:设置少数类集合 A. 对于每个属于 A 的 x,找到 x 的 k 个最近邻(通过计算 x 与集合 A)中每隔一个少数点的欧氏距离)
A = {x1,x2,…XT }&x1 的 k 近邻= {x6,x7,…xk} &相似
**第二步:**对于每一个属于 A 的 x,从其 k 个最近邻中选择 n 个少数点,它们构成集合 A1。
x1 的 x1 = { x7,x4,…xn}
**第三步:**为每个点 p 中的 A 生成一个新的样本
新点= p + rand(0,1) * |p-x1|
其中 rand(0,1)表示 0 和 1 之间的随机数
图 2 .作者对 SMOTE 功能的概述
SMOTE 仍然是一个有趣的工作,许多研究工作已经引入了 SMOTE 的变体,这些变体具有以它们自己的方式合成新的少数点的不同方法。SMOTE 的原始论文被引用超过 5000 次,开发 SMOTE 扩展的研究仍然是新鲜的。边界线-SMOTE(韩等,2005),安全级-SMOTE (Bunkhumpornpat 等,2009),DBM SMOTE(Bunkhumpornpat 等,2012),ROSE (Menardi & Torelli,2014),MWMOTE (Barua 等,2014),(Abdi & Hashemi,2016),Geometric SMOTE(Douzas 等,2017)就是相当多的例子。
我发现 Geometric SMOTE 很有趣,因为它利用几何来优雅地开发解决方案,识别和解决可能导致的潜在问题。虽然它被称为 SMOTE 的变体,但不是真正的扩展。它模仿合成新的少数样本的核心思想。几何 SMOTE 也是一种基于该原理和插值的算法。让我们进入几何 SMOTE 的症结。
几何 SMOTE
现有的 SMOTE 及其变体具有在合成少数样本时必须解决的各种问题,并且几何 SMOTE 已经确定了如下问题。
- 噪声示例的生成
当合成新的少数样本时,在多数聚类空间中合成特定样本的可能性更高。这种数据被称为噪声点。它们只能作为噪声融入集群。
图 3 .从几何 SMOTE 纸上获取的噪声样本的生成
在上面的图 3 中,噪声样本是选择x’
作为应用 SMOTE 的最近点的结果。
图 4 .来自几何 SMOTE 纸的噪声样本-2 的生成
由于点的选择,还有另一种最终产生噪声样本的可能性。在图 4 中。由于x
已经是一个噪声点,并且所选择的点也是噪声点,所以所生成的样本最终也是一个噪声样本。
图 5 .来自几何 SMOTE 纸的噪声样本-3 的生成
在上面的图 5 中,同样通过选择随机选择的x
和x’
,生成的点落在多数簇内,并导致噪声样本的形成
2.属于相同子聚类的样本的生成导致过度拟合和不适当的表示。
图 6 .几乎相似样本的生成
这里,虽然不存在噪声样本的问题,但是生成属于一个少数子聚类的新样本会引入“聚类内不平衡”并导致原始数据的偏斜表示。并且高度密集的子群的新样本的生成将导致
G-SMOTE 的主要目标
Smote 在确定潜在泄漏后,确定了其主要目标,以解决一些问题和解决问题的机制。
- G-SMOTE 想要定义一个安全区域来合成新点。这是为了确保没有合成点被生成为噪声样本。
- G-SMOTE 希望增加生成的少数类样本的多样性。这将防止少数样本的相同子类的生成导致群内偏斜。
G-SMOTE 的参数
Smaj :多数类样本集。
Smin :少数类样本集。
N :要生成的合成样本总数。
k :最近邻数。
α_ trunc:1≤α_ trunc≤1 的截断因子。
α_ def:0≤α_ def≤1 的变形因子。
α_sel :带有α_ sel∈n {少数,多数,组合}的邻居选择策略
S_gen:生成的合成示例集。(输出)
算法
关于完整的算法和解释,请参考 G-SMOTE 论文。在这里,我希望用例子来解释算法,并抽象出来。
1.对 Smin 元素进行混洗,并初始化空集 Sgen
**Smaj = {smaj1,smaj2,smaj3,.......}
Smin = {smin1,smin2,smin3,........} -> after being shuffled
Sgen = {}**
2.重复,直到 Sgen 中生成 N 个少数实例:
**N = 0** - Have to run the procedure till N number of samples are generated
2.1.设 x_center ∈ Smin 所选的 p 组件的少数类实例。
- A minority point from Smin is chosen as the center of a geometric region
**x_center** = **smin1**- The order of choosing the minority point will be the order of shuffled data points and in case of **N > size of Smin**, continue to re-run from the beginning again.
2.2.如果 α_sel = minority :
In **G-SMOTE** algorithm they defined 3 neighbor selection strategies ; minority,majority and mixed.- Find the k nearest neighbors of x_center from the set of Smin
**k_nearest_neighbors = {smin6,smin5......}**- randomly select **x_surface** from the **k_nearest_neighbors
x_surface = smin5**- Calculate a radius from the relation
**R ← d(x_center, x_surface)**
2.3.如果 α_sel =多数:
- choose the nearest majority neighbor (from Smaj) of x_center
**x_surface = smaj3**- Calculate a radius from the relation
**R ← d(x_center, x_surface)**
2.4.如果 α_sel = mixed :
- Find the k nearest neighbors of x_center from Smin.
**k_nearest_neighbors** = {smin6,smin5......}- randomly choose one from **k_nearest_neighbors
smin6**- Calculate the euclidean distance
**dmin ← d(x_center, smin6)**----------------------------------------------------------------- Find nearest majority neighbor of x_center from Smaj
**xmaj= smaj3**- Calculate the euclidean distance
**dmaj ← d(x_center, xmaj)**----------------------------------------------------------------- Calculate a radius from the relation
**x_surface ← argmin (dmin, dmaj)**
**R ← d(x_center, x_surface)**----------------------------------------------------------------
**Note: Since d ≤ R ≤ dmaj; where d is distance from x_center to the generated sample
=> G**eneration of noisy samples is avoided
2.5.生成一个合成样本 x_gen ← hyperball(中心=0,半径=1)
图 7。生成 e_sphere
**hyberball**:- function is meant for creating the e-sphere- **e_sphere** is generated on the surface of a unit hyper-sphere
2.6.通过 x_gen ← truncate(x_gen,x_center,x_surface,α_trunc) 变换 1 合成样本。
图 8 .α_ trunc 的截断效应
**Truncation:**- defined with bit of complex mathematics. But intuitively tells us which side of the hyper-sphere to be truncated to secure a safe space to generate a minority sample. - When **α_trunc** > 0, the area that is opposite to the x_surface is truncated from the interior of the hyper-sphere.- When **α_trunc** < 0, the truncation occurs in the area that includes the x_surface point.- **α_trunc v**alue is generally -1 to 1\. If it is -1.0, it truncates the exact **semi**-hyper sphere on the same side of surface point and truncates the opposite side of **semi**-hyper sphere if **α_trunc equals** 1.0
2.7.通过 x_gen ← deform(xgen,xcenter,xsurface,α_def)变换 2 合成样本。
图 9 .变形对α_def 的影响
**Deformation:**
- corresponds to the deformation of the hyper-sphere in to a hyper-spheroid- **α_def** relates the story of hyper-plane that to be chosen on which the new minority sample will be synthesized- **α_def** typically takes value 0 to 1 allowing the Deformation method to choose the proper plane to place generated sample.
2.8.通过 x_gen ← translate(xgen,xcenter,R)转换 3 合成样本。
**Translation:**- translation of the generated point by the x_center vector and the resealing by the value of the radius R- return (x_center + R * x_gen)
图 10 .少数样本的生成
2.9.将生成的样本 x_gen 添加到生成的样本 S_gen 的集合中
**S_gen {x_gen}
N = N+1**
感谢阅读 G-SMOTE 到这一步。该博客旨在对 SMOTE 及其变体中的问题、G-SMOTE 算法和主要目标进行概述。看到 G-SMOTE 算法的缺点也很有趣,让我们在一个单独的博客中讨论它们。
参考
[1] Johnson,J.M .,Khoshgoftaar,T.M .关于深度学习存在类不平衡的调查。 J 大数据 6、 27 (2019)。https://doi.org/10.1186/s40537-019-0192-5
[2] N. V .舒拉, K. W .鲍耶, L. O .霍尔, W. P .凯格尔迈耶 (2011)。“SMOTE:合成少数过采样技术”
[3]圣乔治·杜萨斯和费尔南多·巴桑。(2017).几何 SMOTE:通过 SMOTE 的几何扩展实现不平衡学习的有效过采样。
[4] G. Douzas 和 F. Bacao,“几何 SMOTE 对 SMOTE 的一种几何增强的插入式替代”,信息科学,第 501 卷,第 118–135 页,2019 年。可用:10.1016/j.ins.2019.06.007
[5] G-SMOTE 实现—https://github.com/AlgoWit/geometric-smote
处理“缺失”数据?
所有数据集都有个缺失值。
这些可以是难、未定义或空— 的形式,也可能是别的什么?
但是我们该拿它们怎么办呢?我们应该删除这些行还是替换这些值?让我们看看如何以一种理智的方式摆脱这些缺失的价值观。
数据无处不在,但也有缺失值。[斯蒂芬·道森在 Unsplash 上拍照]
替换数据集中缺失的值称为数据输入。
现在,一些数据科学的从业者可以说——对这些价值“不做任何事情”。但是不要这样做,大多数算法在遇到缺少值的数据时都会抛出错误。
让我们考虑一下熊猫的数据框架:
一个示例数据帧。[图片由作者提供]
那么,我们能做些什么来填补这些缺失的价值呢?
1.使用每列的“平均值”。
用每列的平均值填充 NaN 值。[图片由作者提供]
这是一个快速的解决方案,但是“均值”作为一个统计数据是不稳定的,并且它不能很好地与分类特征相适应。此外,如果数据是倾斜的,就不会考虑相关性。
这也会影响结果数据集的方差,因此要小心,如果训练 ML 算法时缺失数据用均值填充,这可能会导致较高的偏差。
2。使用每列中“最频繁”的值。
现在让我们考虑一个新的数据框架,一个具有分类特征的数据框架。
具有分类特征 1 和 2 的示例数据框。[图片由作者提供]
我们可以用众数来替换丢失的值——或者每列中出现最频繁的值。这同样没有考虑到相关性,并且由于不希望地将更多标签分配给特定类别,可能会在数据中引入偏差。
如何使用模式填充分类特征?[图片由作者提供]
但是上述方法主要适用于小数据集,如果您有一个大数据集呢?
大数据是不是变得太大了?[Giphy 的 GIF 图
让我们来看一个多了几行和几列的数据帧。
更大的数据框架。[图片由作者提供]
3.在每列中使用“内插法”。
现在让我们使用上面显示的数据框架,我们可以沿着每一列使用插值来填充缺失的值。
*但是插值有什么用呢?*它启动适合您数据的功能。然后,该函数可用于推断缺失数据的值。
在熊猫中有不同的插值策略,如线性或多项式。请记住,如果您使用多项式策略,您将需要指定插值多项式的阶。
2 阶多项式插值后的结果。[图片由作者提供]
它在计算上比我们上面介绍的两种方法更昂贵,但是取决于用于插值的策略;它能给出更好的结果。
4。使用其他方法,如 K-最近邻法。
上面显示的三种方法在 Pandas 的框架内工作。但是如果你可以访问其他像scikit-learn
这样的库,你也可以访问KNNImputer
。让我们考虑将它与方法 3 中使用的数据帧一起使用。
KNNImputer的工作原理是每个新点如何与数据中的所有其他点相似。因此,通过检查数据集中的 k 个最近邻是否有缺失值,我们可以基于邻域或最近的“k 点”对它们进行估算。
总的来说,这种方法比上面提到的三种方法更加通用,因为它适用于所有类型的数据——连续数据、离散数据和分类数据。
结果使用邻居为 2 的 KNNImputer 后。[图片由作者提供]
如果您知道任何其他填充数据集中缺失值的常用方法,请在评论中注明。
我希望你觉得这篇文章有趣并且有用。
ℹ️ℹ️ℹ️ℹ️ℹ️ℹ️ℹ️ℹ️ℹ️ℹ️谢谢你!
处理缺失数据
PyTrix 系列
PyTrix #7:处理缺失数据的各种技术
照片由埃米利亚诺·维托里奥西在 Unsplash 拍摄
在 PyTrix 的上一个系列(Pandas 的缺失数据一瞥)中,我们提到了缺失数据和使用 Pandas 框架检测缺失值;这是那一集的摘录“当我们观察到数据中缺少值时,这是因为没有数据值存储在观察的变量中。缺失数据在实践中极为常见,会对从数据中得出的结论产生很大影响,因此数据科学家的大部分时间都花在了数据清理上。”
尽管我们探索了检测缺失数据的方法,但是我们并没有给出一个明确的解决方案来解决这个问题。在这篇文章中,我希望介绍一些我认为有用的策略,因为这是 PyTrix,当然我会分享一些有用的 Python 代码,我们可以用它们来完成这些任务。
注意:可以通过下面的链接访问完整的笔记本。此外,这篇文章是直接从 Jupyter 笔记本上创建的——要了解我是如何做到的 点击这里 。
permalink dissolve GitHub 是超过 5000 万开发人员的家园,他们一起工作来托管和审查代码,管理…
github.com](https://github.com/kurtispykes/demo/blob/master/pytrix/pytrix_handling_missing_data.ipynb)
我们将使用来自 Kaggle 的臭名昭著的泰坦尼克号数据集,点击此处即可访问。
import numpy as np
import pandas as pd# reading the data
df = pd.read_csv("../data/titanic_raw/train.csv")
df.tail()
图 1
我们可以在图 1 的年龄和客舱列中看到一些NaN
值,但是通过这种方式查看我们的数据将很难看出我们有多少缺失的数据。更好的解决方案是使用df.info()
,它将为我们提供每一列的非空计数和数据类型——参见文档
# information on the columns
df.info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 PassengerId 891 non-null int64
1 Survived 891 non-null int64
2 Pclass 891 non-null int64
3 Name 891 non-null object
4 Sex 891 non-null object
5 Age 714 non-null float64
6 SibSp 891 non-null int64
7 Parch 891 non-null int64
8 Ticket 891 non-null object
9 Fare 891 non-null float64
10 Cabin 204 non-null object
11 Embarked 889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
所有列都有 891 个观察值,但我们在年龄列中只有 714/891 个非空观察值,在客舱列中有 204/891 个非空观察值,在上船列中有 889/891 个非空观察值。
在处理这些丢失的值之前,我必须指出,在理想情况下,我们应该对现有的数据进行深入分析,因为我们想首先了解数据丢失的原因。此外,在处理缺失值时,与领域专家交谈(如果你不是)也是一个重要的步骤,这样我们可以确保我们使用的任何技术都是合理的(从统计角度看),并且我们仍然可以从我们的模型中获得准确的预测。
原因很简单,如果缺失数据降低了样本的代表性,并因此扭曲了关于人口的推断,那么对于我们处理这个问题来说,确保我们的模型能够准确代表人口是至关重要的。
由于我们的目的是探索处理缺失数据的各种技术,我们可以假设前面的需求已经实现。
删除
处理丢失数据的最简单方法是删除它们。也称为列表式删除,在这种方法中,如果一行缺少一个值,我们将从分析中删除整行。
df2 = df.copy()
print("Before removing rows with missing values")
print(df2.shape)
print("After removing rows with missing values")
df2.dropna(inplace=True)
print(df2.shape)Before removing rows with missing values
(891, 12)
After removing rows with missing values
(183, 12)
从我们的数据中删除行可能会带来更多的伤害,而不是公正。在这个例子中,我们删除了 708 行(占观察值的 20.5%),考虑到我们的样本大小,这是一个相当大的数据量。这是有问题的,因为减少数据量会降低我们分析的统计能力,因为这部分依赖于高样本量。
此外,如果缺失数据的原因不是随机的,如果我们决定进行列表式删除,我们将会在结果中产生偏差。非随机缺失数据的一个例子是当插入问题(例如,你挣多少?)在问卷中被问到。许多人可能不愿意分享这些信息,但回答其他问题却没有问题。这种偏见可能会发生,因为决定回答每个问题(包括干扰性问题)的人可能与不愿意回答干扰性问题的参与者有着非常不同的特征。
**注意:**如果变量丢失了大部分数据,我们可以创建一个二进制标志变量来表示丢失(1)或不丢失(0),并删除带有丢失值的初始列。
归罪
接下来的几项技术更侧重于插补,即使用替代值替换缺失数据的过程。尽管列表式删除因其简单性而成为处理缺失数据的最常见方式,但它也有缺陷。插补可以被视为避免这些陷阱的一种方法。
热甲板
这是从随机选择的相似记录中估算缺失值的地方。热卡插补的一种形式是最后一次观察结转(LOCF 插补)。LOCF 所做的是找到第一个缺失值,然后使用紧邻的前一个单元格的值来估算缺失值。这种方法符合这样一种信念,即最佳猜测是数据自上次测量以来没有发生变化。我们将用 Python 实现它。
# looking at the data before imputation
df_hot_deck = df.copy()
df[887:]
图 2
现在,我们将对该数据帧执行 LOCF,这将使用缺失值上方的单元格来估算所有缺失值
# looking at the data after imputation
df_hot_deck.fillna(method="ffill", inplace=True)
df_hot_deck[887:]
图 3
众所周知,使用这种方法估算数据会增加偏差的风险,并可能导致我们的数据得出错误的结论,因此通常不建议使用这种方法——我不太确定人们是否在实践中使用这种方法。
统计方法
从技术上讲,这可能不是用来描述这些技术的正确术语,但是我想要一个总括术语,它将捕捉我们可以使用统计来估算我们的数据的所有不同方式。常见的统计有均值、中值和众数。
# View all rows with a missing age
df3 = df.copy()
missing_age = df3[df3["Age"].isna()].index
df3[df3["Age"].isna()]
图 4
# imputing all rows with missing age with the mean age
df3["Age"].fillna(df3["Age"].mean(), inplace=True)
df3.loc[missing_age]
图 5
均值插补减弱了任何涉及插补特征的相关性-保证插补变量和任何其他测量变量之间没有关系,这意味着这对于单变量数据来说可能是一种非常好的方法,但对于多变量来说不是很好-我们可以对分类数据使用模式值。
# current value counts of the embarked column
df3["Embarked"].value_counts(dropna=False)S 644
C 168
Q 77
NaN 2
Name: Embarked, dtype: int64# view rows with missing values
missing_embarked = df3[df3["Embarked"].isna()].index
df3[df3["Embarked"].isna()]
图 6
# fill the rows with missing values and view them
df3["Embarked"].fillna(df["Embarked"].mode()[0], inplace=True)
df3.loc[missing_embarked]
图 7
模型插补
同样,这可能是我用来命名这种现象的不好的术语。处理缺失数据插补的一种流行方法是使用模型来预测缺失值。尽管 kNN 已经被证明是非常有效的(通常被称为最近邻插补),但是有许多模型可供选择。
from sklearn.impute import KNNImputerX = df[["Survived", "Pclass", "Age", "SibSp", "Parch", "Fare"]].copy()
knn_imputer = KNNImputer(n_neighbors=3)
filled_df = pd.DataFrame(data=knn_imputer.fit_transform(X),
columns=["Survived", "Pclass", "Age", "SibSp", "Parch", "Fare"])
filled_df.loc[missing_age]
图 8
KNNImputer
的文档声明“使用训练集中找到的 n_neighbors 最近邻的平均值估算每个样本缺失值。如果两个样本都不缺少的特征是接近的,则这两个样本是接近的。”。因此,我移除了所有对象数据类型,因为这将在此算法的中引发错误。
注意:也有其他算法内置了处理缺失值的方法,比如 XGBoost
如果您想与我联系,请在 LinkedIn 上留下回复或与我联系。
[## Kurtis Pykes -人工智能作家-走向数据科学| LinkedIn
在世界上最大的职业社区 LinkedIn 上查看 Kurtis Pykes 的个人资料。Kurtis 有一个工作列在他们的…
www.linkedin.com](https://www.linkedin.com/in/kurtispykes/?originalSubdomain=uk)
处理缺失值专用 pythonic 指南
入门
处理缺失值的 3 种最佳方法
Ehimetalor Akhere Unuabona 在 Unsplash 上拍摄的照片
对于大多数数据科学项目来说,处理缺失值是探索性数据分析(EDA)的关键步骤,无论是开发机器学习模型还是商业分析。包括 scikit-learn 在内的大多数库都不会使用带有缺失值的数据来构建模型。由于数据量巨大,找到获得最佳估算值结果的技巧是成为独角兽数据科学家的巨大优势。在本文中,我们将回顾 3 个最成功的开源短 python 代码行,它们可以组合起来处理缺失值。
在这篇文章中,我们将分析样本 flowers、titanic 和 house prices Kaggle 数据集,您可以在这里找到。
简介
有许多处理丢失值的场景,丢失的数字在 python 中通常表示为 nan ,这是“不是数字”的缩写。传统的方法是检测缺少值的单元格,并使用以下命令计算它们在每一列中的数量:
missing_val_count_by_column = (data.isnull().sum())print(missing_val_count_by_column[missing_val_count_by_column > 0
大多数 Kaggle 比赛中都有 3 种主要方法,让我们来回顾一下:
1。 效率较低:删除缺少值的列
删除缺少值的列的一种方法是在训练/测试数据帧中删除相同的列,如下所示:
从原始数据帧:
data_without_missing_values = original_data.dropna(axis=1)
通过训练,测试数据帧:
cols_with_missing = [col for col in original_data.columnsif original_data[col].isnull().any()]reduced_original_data = original_data.drop(cols_with_missing, axis=1)reduced_test_data = test_data.drop(cols_with_missing, axis=1)
删除丢失的值后,您的模型将无法访问该列,从而导致重要数据的丢失。但是,当列中的大多数值都丢失时,这种策略可能是合适的。
一个更好的选择:插补
比删除数据集列更好的选择是用数据分布平均值填充缺失值,如下所示:
from sklearn.impute import SimpleImputermy_imputer = SimpleImputer()data_with_imputed_values = my_imputer.fit_transform(original_data)
该选项通常集成在 scikit-learn 管道中,使用比平均值更复杂的统计指标。管道是简化模型验证和部署的关键策略。
3)最佳选择
最后一种策略是系统地随机填充缺失值。如果您需要获得最佳结果,您需要考虑您的列统计指标。下面是它可能的样子:
#制作副本以避免更改原始数据(输入时)
new_data = original_data.copy()
#制作新栏,说明将估算的内容
cols_with_missing = (col for col in new_data.columnsif new_data[col].isnull().any())for col in cols_with_missing:new_data[col + ‘_was_missing’] = new_data[col].isnull()
#插补
my_imputer = SimpleImputer()new_data = pd.DataFrame(my_imputer.fit_transform(new_data))new_data.columns = original_data.columns
在大多数情况下,这种方法会大大改善你的结果。
案例分析
现在让我们用最著名的 Kaggle 数据集来练习。我们将回顾泰坦尼克号,花卉,价格住房卡格尔竞争数据集的例子。
为了掌握缺失值处理,我建议您使用本笔记本 遵循每个步骤,并对您的数据集重复相同的步骤。
照片由руслангамзалиев在 Unsplash 上拍摄
1.泰坦尼克
data = pd.read_csv(‘../input/titanicdataset-traincsv/train.csv’)
泰坦尼克号数据集(891 行× 12 列) ( 图片由作者提供)
from sklearn.ensemble import RandomForestRegressorfrom sklearn.metrics import mean_absolute_errorfrom sklearn.model_selection import train_test_splittitanic_target = data.Survivedtitanic_predictors = data.drop(‘Survived’, axis=1)
为了保持例子简单,我们将只使用数字预测器。
titanic_numeric_predictors = titanic_predictors.select_dtypes(exclude=[‘object’])X = titanic_numeric_predictors.select_dtypes(exclude=[‘object’])y = titanic_target
#在训练和测试数据集中划分数据。
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2)
方法一
cols_with_missing = [col for col in X_train.columnsif X_train[col].isnull().any()]reduced_X_train = X_train.drop(cols_with_missing, axis=1)reduced_X_test = X_test.drop(cols_with_missing, axis=1)print(“Mean Absolute Error from dropping columns with Missing Values:”)print(score_dataset(reduced_X_train, reduced_X_test, y_train, y_test))
删除缺失值列的平均绝对误差:0.391340782122905
方法二
my_imputer = SimpleImputer()imputed_X_train = my_imputer.fit_transform(X_train)imputed_X_test = my_imputer.transform(X_test)print(“Mean Absolute Error from Imputation:”)print(score_dataset(imputed_X_train, imputed_X_test, y_train, y_test))
插补的平均绝对误差:0.394525139664804
方法三
imputed_X_train_plus = X_train.copy()imputed_X_test_plus = X_test.copy()cols_with_missing = (col for col in X_train.columnsif X_train[col].isnull().any())for col in cols_with_missing:imputed_X_train_plus[col + ‘_was_missing’] = imputed_X_train_plus[col].isnull()imputed_X_test_plus[col + ‘_was_missing’] = imputed_X_test_plus[col].isnull()
#插补
my_imputer = SimpleImputer()imputed_X_train_plus = my_imputer.fit_transform(imputed_X_train_plus)imputed_X_test_plus = my_imputer.transform(imputed_X_test_plus)print(“Mean Absolute Error from Imputation while Track What Was Imputed:”)print(score_dataset(imputed_X_train_plus, imputed_X_test_plus, y_train, y_test))
追踪插补内容时插补的平均绝对误差:0.382178770945
= >最好的方法是:方法 1
2.花
data = pd.read_csv(‘../input/flower-type-prediction-machine-hack/Train.csv’)
花卉数据集(12666 行× 7 列) ( 图片由作者提供)
from sklearn.ensemble import RandomForestRegressorfrom sklearn.metrics import mean_absolute_errorfrom sklearn.model_selection import train_test_splitflower_target = data.Classflower_predictors = data.drop(‘Class’, axis=1)
为了保持例子简单,我们将只使用数字预测器。
flower_numeric_predictors = flower_predictors.select_dtypes(exclude=[‘object’])X = flower_numeric_predictors.select_dtypes(exclude=[‘object’])y = flower_target
#在训练和测试数据集中划分数据。
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2)
方法 1
cols_with_missing = [col for col in X_train.columnsif X_train[col].isnull().any()]reduced_X_train = X_train.drop(cols_with_missing, axis=1)reduced_X_test = X_test.drop(cols_with_missing, axis=1)print(“Mean Absolute Error from dropping columns with Missing Values:”)print(score_dataset(reduced_X_train, reduced_X_test, y_train, y_test))
删除缺失值列的平均绝对误差:1.316111627552926
方法二
my_imputer = SimpleImputer()imputed_X_train = my_imputer.fit_transform(X_train)imputed_X_test = my_imputer.transform(X_test)print(“Mean Absolute Error from Imputation:”)print(score_dataset(imputed_X_train, imputed_X_test, y_train, y_test))
插补的平均绝对误差:1.337274481525667
方法三
imputed_X_train_plus = X_train.copy()imputed_X_test_plus = X_test.copy()cols_with_missing = (col for col in X_train.columnsif X_train[col].isnull().any())for col in cols_with_missing:imputed_X_train_plus[col + ‘_was_missing’] = imputed_X_train_plus[col].isnull()imputed_X_test_plus[col + ‘_was_missing’] = imputed_X_test_plus[col].isnull()
#插补
my_imputer = SimpleImputer()imputed_X_train_plus = my_imputer.fit_transform(imputed_X_train_plus)imputed_X_test_plus = my_imputer.transform(imputed_X_test_plus)print(“Mean Absolute Error from Imputation while Track What Was Imputed:”)print(score_dataset(imputed_X_train_plus, imputed_X_test_plus, y_train, y_test))
追踪插补内容时插补的平均绝对误差:1.392727466344
= >最好的方法是:方法 1
巴黎歌剧院由阿莱西娅·科考尼在 Unsplash 演出
3.房价
data = pd.read_csv(‘../input/house-prices-advanced-regression-techniques/train.csv’)
住房数据集(1460 行× 81 列) ( 图片由作者提供)
from sklearn.ensemble import RandomForestRegressorfrom sklearn.metrics import mean_absolute_errorfrom sklearn.model_selection import train_test_splithouse_target = data.SalePricehouse_predictors = data.drop(‘SalePrice’, axis=1)
为了保持例子简单,我们将只使用数字预测器。
house_numeric_predictors = house_predictors.select_dtypes(exclude=[‘object’])X = house_numeric_predictors.select_dtypes(exclude=[‘object’])y = house_target
#划分训练和测试数据集中的数据。
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2)
方法 1
cols_with_missing = [col for col in X_train.columnsif X_train[col].isnull().any()]reduced_X_train = X_train.drop(cols_with_missing, axis=1)reduced_X_test = X_test.drop(cols_with_missing, axis=1)print(“Mean Absolute Error from dropping columns with Missing Values:”)print(score_dataset(reduced_X_train, reduced_X_test, y_train, y_test))
删除有缺失值的列后的平均绝对误差:36860 . 48686863686
方法二
my_imputer = SimpleImputer()imputed_X_train = my_imputer.fit_transform(X_train)imputed_X_test = my_imputer.transform(X_test)print(“Mean Absolute Error from Imputation:”)print(score_dataset(imputed_X_train, imputed_X_test, y_train, y_test))
插补的平均绝对误差:18960 . 686868686867
方法 3
imputed_X_train_plus = X_train.copy()imputed_X_test_plus = X_test.copy()cols_with_missing = (col for col in X_train.columnsif X_train[col].isnull().any())for col in cols_with_missing:imputed_X_train_plus[col + ‘_was_missing’] = imputed_X_train_plus[col].isnull()imputed_X_test_plus[col + ‘_was_missing’] = imputed_X_test_plus[col].isnull()
#插补
my_imputer = SimpleImputer()imputed_X_train_plus = my_imputer.fit_transform(imputed_X_train_plus)imputed_X_test_plus = my_imputer.transform(imputed_X_test_plus)print(“Mean Absolute Error from Imputation while Track What Was Imputed:”)print(score_dataset(imputed_X_train_plus, imputed_X_test_plus, y_train, y_test))
追踪插补内容时,插补的平均绝对误差:18941
= >最好的方法是:方法 1
结论
如果你有空闲时间,我建议你读读这篇文章:
[## Kaggle 初学者 5 天数据清理挑战:第 1 天-处理缺失值
最大的数据科学平台 Kaggle 刚刚为数据初学者发起了为期 5 天的数据清理挑战…
medium.com](https://medium.com/@smeshram258/kaggle-5-day-data-cleaning-challenge-for-beginners-day-1-handling-missing-values-ee48b01e69cb)
总结
参考此链接,使用这些方法对这些数据集进行完整的缺失数据分析。
这个简单的概述提醒了在数据科学中使用 python 处理缺失值时使用多种方法的重要性。这篇文章涵盖了 3 个基本的 Python 处理缺失值,以创建一个完整的探索工作流,以及有用的文档。
希望你喜欢,继续探索!!!
用熊猫处理缺失值
关于如何检测和处理缺失值的完整教程
由 Unsplash 上的 chuttersnap 拍摄
数据科学项目中最耗时的部分是数据清理和准备。然而,有许多强有力的工具可以加速这个过程。其中之一是 Pandas,它是一个广泛使用的 Python 数据分析库。
处理缺失值是数据清理和准备过程中必不可少的一部分,因为现实生活中几乎所有的数据都带有一些缺失值。在这篇文章中,我将解释如何使用 Pandas 来检测丢失的值并以一种正确有效的方式处理它们。
让我们先创建一个缺少值的数据帧。
np.nan、None 和 NaT(对于 datetime64[ns]类型)是熊猫的标准缺失值。
**注意:**Pandas 1.0 中引入了一种新的缺失数据类型(< NA >),它是一种整数类型的缺失值表示。
np.nan 是浮点型的,所以如果你在一列整数中使用它们,它们将被转换成浮点数据类型,正如你在我们创建的 dataframe 的“column_a”中看到的。但是,可以和整数一起使用,不会导致向上转换。让我们使用向 dataframe 再添加一列,可以通过显式请求 dtype Int64Dtype()来使用它。
查找缺失值
Pandas 提供了 isnull() , isna() 函数来检测缺失值。他们俩做着同样的事情。
df.isna() 返回带有布尔值的 dataframe,该值表示缺少的值。
也可以选择使用与 isna()正好相反的 notna() 。
df.isna()。any() 为每一列返回一个布尔值。如果该列中至少有一个值缺失,则结果为真。
df.isna()。sum() 返回每列中缺失值的数量。
处理缺失值
并非所有缺失的值都是简洁明了的 np.nan 或 None 格式。比如,“?”数据帧 c 列中的“—”字符没有给我们任何有价值的信息或见解,因此本质上它们是缺失值。但是,这些字符无法被熊猫检测为缺失值。
如果我们知道哪种字符用作数据集中的缺失值,我们可以在使用 na_values 参数创建数据帧时处理它们:
另一种选择是在创建数据帧后使用 pandas replace() 函数来处理这些值:
我们已经用 NaN 值替换了非信息单元格。就地参数保存数据帧中的变化。inplace 的默认值为 False,因此如果将其设置为 True,将不会保存更改。
没有处理缺失值的最佳方法。根据数据集和任务的特征,我们可以选择:
- 删除缺少的值
- 替换丢失的值
删除缺少的值
我们可以使用 dropna() 函数删除带有缺失值的行或列。如何用参数设置条件下降。
- how='any ':如果有任何缺少的值,则删除
- how='all ':如果所有值都丢失,则删除
此外,使用 thresh 参数,我们可以根据非缺失值的数量设置一个阈值,以便删除一行/一列。
thresh 参数要求一行或一列至少要有指定数量的非缺失值才能不被删除。例如,如果我们将 thresh 参数的值设置为 3,则一列或一行必须至少有 3 个非缺失值才不会被删除。没有 3 个或更多非缺失值的行或列(取决于轴参数的值)将被删除。
轴参数用于选择行(0)或列(1)。
我们的 dataframe 没有一行充满缺失值,因此设置 how='all ‘不会删除任何行。缺省值是’ any ',所以如果我们想使用 how='any ',就不需要指定它:
至少有一个值缺失的行已被删除。
将 thresh 参数设置为至少有 3 个非缺失值的 3 个已删除行。
数据是宝贵的资产,所以我们不应该轻易放弃它。此外,机器学习模型几乎总是倾向于在更多数据的情况下表现更好。因此,根据具体情况,我们可能更喜欢替换丢失的值,而不是丢弃。
替换缺失值
fillna() 熊猫的功能方便处理缺失值。使用 fillna(),缺失值可以由特殊值或聚合值(如平均值、中值)替换。此外,缺失的值可以用它之前或之后的值替换,这对时间序列数据集非常有用。
- 用标量替换丢失的值:
- fillna()也可以用于特定的列:
- 使用方法参数,缺失的值可以用它们之前或之后的值替换。
ffill 代表“向前填充”用前一行的值替换缺失的值。您也可以选择 bfill 代表“反向填充”。
如果一列或一行中有许多连续的缺失值,您可能希望限制向前或向后填充的缺失值的数量。
极限参数设置为 1,因此只有一个缺失值被向前填充。
感谢您的阅读。如果您有任何反馈,请告诉我。
我的其他帖子
ML 模型中多重共线性的处理
提高线性回归模型可解释性的简单方法
图片来自 Unsplash
多元线性回归模型用于模拟响应/因变量和解释/自变量之间的关系。然而,多重共线性、误差项方差相关性、非线性等问题影响了模型的可解释性。本文将讨论多重共线性、多重共线性的影响以及处理多重共线性的技术。
什么是多重共线性?
当被假定为相互独立的解释变量被揭示为相互密切相关时,这种相关性被称为共线性。当观察到两个或更多解释变量的相关性时,称为多重共线性。
多重共线性尤其不可取,因为**它会影响线性回归模型的可解释性。**线性回归模型不仅有助于建立响应变量和解释变量之间的关系,还有助于确定每个解释变量对响应变量的个别影响。
因此,由于多重共线性的存在,很难分离出这些单独的影响。换句话说,多重共线性可以被视为一种现象,其中两个或更多的解释变量彼此高度线性相关,以至于一个解释变量可以从另一个解释变量以相当高的准确度预测。
多重共线性的影响
由于共线性/多重共线性的存在,很难隔离解释变量对响应变量的个别影响。
多重共线性会导致以下结果:
- **系数估计的不确定性或不稳定方差:**数据的微小变化(添加/删除行/列)会导致系数的变化。
- **标准误差增加:**降低估计的准确性,增加检测的机会。
- **统计显著性下降:**由于标准误差增加,t-统计下降,这对检测系数中的统计显著性的能力产生负面影响,导致 II 型误差。
- **缩减系数& p 值:**由于共线性,相关解释变量的重要性被掩盖。
- **过度拟合:**导致过度拟合,如高方差问题所示。
如何检测多重共线性?
除了观察上述影响的模型行为之外,多重共线性也在相关值中进行了定量捕捉。因此,可以使用以下内容:
相关矩阵:
数据中两个变量之间的皮尔逊相关性在-1 到 1 之间变化。两个变量的数据类型应为数值型,以便计算皮尔逊相关值。
这里,使用 r 的自动 MPG 数据集的相关矩阵。列名包含字符串,因此被删除。响应变量是 mpg,它代表燃油消耗效率。
#data = Auto
#generate correlation matrix in Rcorrelation_matrix <- cor(Auto[, -which(names(Auto) == "name")])
Autompg 数据集的相关矩阵;作者图片
可以观察到气缸和排量、马力和重量之间的高度相关性。此外,还有几对具有高度正/负相关性的解释变量。因此,存在多重共线性。
然而,正如人们会注意到的,对 8 个变量来说,浏览表格并识别这些变量是令人厌倦的,而且随着变量数量的增加,情况只会变得更糟。因此,关联热图是更直观的关联表示。
关联热图:
关联热图通过调整正负关联的颜色和大小来帮助更好地可视化数据。
在 R 中,corrplot 包可以用来创建相关性的热图。
library(corrplot)
corrplot(correlation_matrix, type = "upper", order = "hclust", tl.col = "black", tl.srt = 45)
Autompg 数据集的关联热图;作者图片
热图无疑更加直观和可视化。但是,它有助于严格识别 2 个变量之间的相关性,而无法识别 3 个或更多变量之间存在的共线性,对此可以使用方差膨胀因子。
方差膨胀因子(VIF): VIF 是拟合完整模型时系数估计的方差除以系数估计的方差(如果单独拟合的话)的比值。最小可能值为 1,表示没有共线性。如果值超过 5,则应解决共线性问题。
library(rms)
multiple.lm <- lm(mpg ~ . -name, data = Auto)
summary(multiple.lm)
vif(multiple.lm)
Autompg 数据集的 VIF 值;作者图片
气缸、排量、马力和重量的 VIF 值远高于 5,因此应该处理,因为数据中的共线性很高。
处理多重共线性
多重共线性可以用以下两种方法处理。注意,自变量之间的这种相关性会导致数据冗余,消除这种冗余有助于消除多重共线性。
- **引入惩罚或删除高度相关的变量:**使用 lasso 和岭回归来删除提供冗余信息的变量。这也可以通过观察 VIF 来实现。
- **组合高度相关变量:**由于共线变量包含冗余信息,使用 PCA 等方法将其组合成单个变量,生成自变量。
对于在 R 中实现的 Autompg 线性回归模型,请查看这个 Github 库。 该库探究多重共线性以及线性回归模型的交互项和非线性转换。
参考:
R 中的统计学习导论。
使用轮廓分析处理聚类中的异常值
从 K 均值聚类中识别并移除每个聚类中的异常值
图片由皮克斯拜的 Gerd Altmann 提供
现实世界中的数据通常有很多异常值。异常值的原因可能是数据损坏或未能记录数据。异常值的处理在数据预处理过程中非常重要,因为异常值的存在会妨碍模型发挥最佳性能。
有各种策略来处理数据集中的异常值。本文将介绍如何在使用剪影分析将数据聚类成几个簇之后处理异常值。
轮廓分析:
剪影法是一种寻找最佳聚类数以及解释和验证数据聚类一致性的方法。剪影方法计算每个点的剪影系数,该系数测量一个点与其自己的聚类相比与其他聚类相似的程度。通过提供一个简洁的图形表示来显示每个对象的分类情况。这些图形表示的分析被称为轮廓分析。
剪影值是一个衡量对象与其自身聚类(内聚)相比与其他聚类(分离)相似程度的指标。轮廓值的范围在[1,-1]之间。
**Important Points:
The Silhouette coefficient of +1** indicates that the sample is far away from the neighboring clusters.
**The Silhouette** coefficient **of 0** indicates that the sample is on or very close to the decision boundary between two neighboring clusters.
**Silhouette** coefficient **<0** indicates that those samples might have been assigned to the wrong cluster or are outliers.
计算轮廓系数:
求第 I 个点的轮廓系数的步骤:
- 计算 an (i):该点与同一聚类中所有其他点的平均距离。
- Compute b(i):该点与离其聚类最近的聚类中所有点的平均距离。
- 使用下述公式计算 s(I)-轮廓系数或第 I 点。
(图片由作者提供),a(i)和 b(i)的图解表示,根据上述公式计算轮廓系数— s(i)
使用轮廓分析找到“k”的最佳值:
使用剪影法寻找最佳的聚类数。也可以用肘法找到,但剪影法被认为是比肘法更好的方法。阅读以下文章了解更多信息:
k-Means 聚类中寻找最优聚类的剪影法深度分析
towardsdatascience.com](/silhouette-method-better-than-elbow-method-to-find-optimal-clusters-378d62ff6891)
(图片由作者提供),**左:**平均距离与聚类数,**右:**剪影得分与聚类数
轮廓图显示了一个聚类中的每个点与相邻聚类中的点的接近程度,从而提供了一种视觉评估聚类数量等参数的方法。
轮廓分析的关键要点:
- 从不同 n_clusters 值的侧影线图和侧影分析,观察到 n_cluster=3 是聚类数(k)的最佳值。
- 在上面的“剪影分析,用于对样本数据进行 KMeans 聚类,n_clusters=3 ”的图像中,观察到所有聚类[0,1,2]的大部分点的剪影系数大于平均剪影分数。
- 在上面的“对样本数据进行 KMeans 聚类的剪影分析,n_clusters=3 ”的图像中,可以观察到,对于 cluster_label 2,很少有点具有负剪影系数,可以将其视为异常值。同样对于 cluster_label 1,一些点的轮廓系数小于平均轮廓得分,这些点位于远离其聚类中心的聚类边界上。
要查找异常值,请查找具有负轮廓系数的点,并将其移除。位于远离聚类中心的聚类边界上的点也可以被移除以创建健壮的模型,但是这取决于案例研究。
参考资料:
[1]维基百科:剪影(聚类),(2020 年 9 月 14 日)
[2] Scikit 学习文档:通过对 KMeans 聚类进行轮廓分析来选择聚类数
感谢您的阅读
熊猫分组及其多指标处理
熊猫群入门
Pandas groupby 方法产生了几个级别的索引和列
Pandas 被认为是任何使用 Python 的数据科学家的必备工具。一个常用的特性是groupby
方法。然而,那些刚刚过渡到 pandas 的人可能会觉得有点困惑,尤其是如果你来自 SQL 的世界。
为了比较,我们先来看看GROUP BY
在 SQL 中是如何工作的。我们将使用几个部门的手术数据集,其中包含手术时间的信息:
要获得 SQL 中过程的平均长度:
SELECT department, procedure_name, COUNT(*) AS count, AVG(procedure_minutes) AS length
FROM cases
GROUP BY procedure_name
ORDER BY department
ORDER BY
部门允许我们对属于同一个部门的程序进行分组。
输出:
这几乎相当于熊猫使用groupby
:
gp = cases.groupby(['department','procedure_name']).mean()
gp
输出:
如您所见,我们遗漏了计数列。通过直接调用mean
函数,我们不能插入多个聚合函数。让我们通过使用agg
函数来解决这个问题:
gp = cases.groupby(['department','procedure_name']).agg(['mean', 'count'])
gp
输出:
太好了,现在这个看起来更熟悉了。注意程序 _ 会议记录标题与部门和程序 _ 名称标题不对齐。这就是我们开始看到 SQL 表和 pandas 数据帧之间差异的地方。
在 SQL 中,从查询派生的每个新表都由列组成。熊猫里有索引和栏目。索引类似于 SQL 的主键列,它唯一地标识表中的每一行。然而,熊猫数据帧可以有多个索引。在这种情况下,部门和程序名都是索引。
要使用索引找到一行,我们只需使用.loc
方法一个接一个地传递索引:
gp.loc[`Cardiology’,‘Pericardiocentesis’]
输出:
在 SQL 中,使用AS
语句重命名*‘过程名称’,**‘计数’和‘过程长度*’列非常简单。因为 pandas 有索引和列,重命名它们有点棘手。要重命名索引:
gp.index.rename(['Department','Procedure'],inplace=True)
gp
输出:
由于这些列有多个级别,重命名它们需要更多的努力:
gp.columns.set_levels(['Length'],level=0,inplace=True)
gp.columns.set_levels(['Count','Mean'],level=1,inplace=True)
gp
输出:
尽管与 SQL 相比,命名列很复杂,但是 pandas 有很多优点。在这篇文章中探索一切可能太长了,但是这里有一个简单的。请注意,甲状腺切除术既可以是耳鼻喉科也可以是普通外科手术。为了获得两个部门的甲状腺切除术的平均值:
gp.xs('Thyroidectomy', level=1)
输出:
但是,如果您仍然喜欢类似于好的 ol’ SQL 的表,只需传入 reset_index :
gp.reset_index(inplace=True)
gp
输出:
这就对了,熊猫分组方法入门。希望有所帮助!
机器学习:处理数据中的缺失值:简单的方法
SciKit 估算器简介
大多数机器学习算法不能处理特征中的缺失值。参见下面墨尔本住房数据的例子。
墨尔本 _ 数据.描述()
这里,BuildingArea 有 7130 行有值,而大多数特性有 13580 行有值。
现在,您可以做一些事情来处理缺失值
1.去掉相应的数据
**melbourne_data.dropna(subset=["BuildingArea"])**
这将删除所有缺少值的行。您可以看到现在行数减少了。
墨尔本 _ 数据.描述()
2.去掉整个属性。
**melbourne_data.drop("BuildingArea", axis=1)**
这将删除整个要素/属性。见下图,建筑面积列现已删除。
墨尔本 _ 数据.描述()
3.将缺少的值设置为某个值
接近 A
如果您认为该属性足够重要,并且必须包含在培训中。您可以填充缺少的值。
用什么填充缺失的值???
你可以用中间值、平均值或零来代替缺失值。
**median = melbourne_data["BuildingArea"].median()
melbourne_data["BuildingArea"].fillna(median, inplace=True)**
这将用计算出的中值替换所有缺失的值。此外,现在您会注意到一件事,即当我们填充了缺少的值时,属性的平均值发生了变化。
墨尔本 _ 数据.描述()
对于**“year build”**属性,您也可以遵循类似的过程。您将不得不保存中间值,因为稍后需要它来填充测试集和新数据中缺失的值(哦,是的,我没有想到)。
方法 B: 引入估算器
SciKit-Learn 提供了 Imputer 类来轻松使用上述任务。您可以按以下方式使用它:
首先,你需要决定策略,它可以是这些策略之一:均值、中值、最频繁
其次,使用决定的策略创建估算器实例
# 1\. Remove categorial
melbourne_data = melbourne_data.select_dtypes(exclude=
[**"object"**]).copy()# 2\. Fit the numerical data to Imputer
**from** sklearn.impute **import** SimpleImputer
imputer = SimpleImputer(strategy=**"median"**)
imputer.fit(melbourne_data)# 3.
X = imputer.transform(melbourne_data)
melbourne_data_tr = pd.DataFrame(X, columns=melbourne_data.columns,
index=melbourne_data.index)
现在,这将计算所有属性的中值,并用各自的平均值填充属性的缺失值。
melbourne_data_tr.describe()
**注意:**不关注类别值,因为它们不在本教程的范围内。
Github 上的代码
Python 代码 : 全文 python 代码用三种方式全部解释。
细流码 : 哦…你也喜欢细流。在此找到 streamlit 代码。
数据 : 二手墨尔本房价数据。
2020 年学习深度学习精选资源
互联网上充斥着各种噪音,很难找到一个进入人工智能世界的真正起点。因此,我包括一些精选的资源,可以帮助你更有效地学习深度学习。这篇文章并不是要给你提供一份你一年都无法完成的资源清单,这篇文章包含了有限的信息,告诉你如何开始、学习,然后向未来的雇主展示你的项目。
注:本文所有观点均为我个人观点。没有任何公司或组织付钱给我来推广他们的课程。
深度学习
如果你知道经典的机器学习,比如(逻辑回归,随机森林,XGBoost ),并且你想转向深度学习,那么这些资源可以帮助你。
理解概念(自下而上的方法):
- deep learning . ai:coursera.org 吴恩达在线授课的最好课程之一。前 3 门课程会帮助你理解深度学习。
通过做项目来理解概念(自上而下的方法):
- 深度学习纳米学位:由 Udacity 提供,是从项目角度学习 DL 的最佳课程之一。
选择深度学习库
如果你希望更快地学习深度学习,你必须选择深度学习库。以下是我可以推荐的几个选项:
- tensor flow/Keras:Google 的开源库。要学习 tensorflow,你可以点击这里的公开课。
Keras 是一个构建在 Tensorlfow 之上的包装器,帮助最终用户快速设计深度学习模型。默认包含在 Tensorflow 的 2.x 版本中。
常见问题:应该学习哪个版本的 tensorflow?
答:您应该直接从版本≥ 2.x 开始。如果您在工业界工作,那么您可能需要阅读 1.x 中的大量代码,因为许多流行的模型都是用 1.x 编写的,但它们仍然与 2.x 兼容。 - Pytorch :脸书的开源库。学习 PyTorch,可以在这里跟着这个公开课。
常见问题:我是否应该选择 Tensorflow 和 Pytorch
回答:这是一个非常主观的答案,取决于你。如果在 2020 年我必须开始学习一个 DL 框架,我肯定会从 Keras 开始。但这里有一个事实,如果你在工业界工作,你将不得不与他们两个一起工作,你没有选择。有些模型在 PyTorch 中实现得很好,有些在 TensorFlow 中实现得很好。
书
- 动手操作 ML 作者 Aurelien Geron:这本书将帮助你学习 ML 和 DL 的基本概念,并将很好地介绍如何使用 Tensorflow 作为深度学习库。请直接去找这本书的最新版本。
- 用 Python 进行深度学习:这本书将帮助你学习 Keras,因为它是 Keras 的创始人 Franchois Chollet 写的。这本书的最新版本将于 2020 年 9 月发布。所以要小心!
- 深度学习书籍:这本书被称为深度学习的圣经,作者是伊恩·古德菲勒、约舒阿·本吉奥和亚伦·库维尔。这本书只免费提供!
- 钻研深度学习:(可选)这本书是由 DeepMind 的研究科学家 Andrew Trask 写的。
通过深度学习选择子职业道路
图一。基于数据的职业选择
现在理想的情况是,你必须决定你是想成为一名处理图像的计算机视觉工程师,还是一名处理文本的自然语言处理/理解/生成工程师。我在这里也包括了演讲,但是演讲没有特别的工作描述,只有文本(出于一些奇怪的原因,我不明白)
计算机视觉
如果你想成为一名摇滚明星,从事图像方面的工作,那么计算机视觉就是你要走的路。
课程:
- CS 231n :斯坦福大学提供。Youtube 视频在这里。这是由费李非(最近进入 Twitter 董事会)和安德烈卡帕西(特斯拉人工智能总监)教授的
- 深度学习专业化课程 4。它包含了卷积神经网络非常坚实的介绍。
书籍:
- 计算机视觉的深度学习:由 Adrian Rosebrock 博士撰写。他是机器学习领域的明星。
项目:
为了制作一个好的投资组合,以下是 Kaggle 的三个顶级项目:
- 钢材缺陷检测:钢材是现代最重要的建筑材料之一。钢结构建筑可以抵抗自然和人为的磨损,这使得这种材料在世界各地无处不在。为了提高钢铁生产的效率,这场比赛将有助于发现缺陷。
- 肺炎检测:这里要求你从胸部的数字图像中检测肺炎,如果你的目标是医学/医疗保健领域的计算机视觉,这是一个很好的比赛。
- 座头鲸识别:这个挑战将教会你暹罗网络的重要性以及如何实现一次性学习。一次性学习就是如何利用一张图片来区分多种鲸鱼。
资源:
- Adrian Rosebrock 的精彩网站,他每周都会发布一篇新文章。如果选择 Tensorflow 作为 DL 库,建议这样做。
- learnopencv.com:萨泰·马里克的精彩网站。代码示例此处。如果选择 Pytorch 作为 DL 库,建议这样做。
自然语言处理
- CS 224n :斯坦福大学的课程。视频是这里。网上免费提供的最好的课程之一。如果你在看完最初的 8 个视频后退出本课程,那也没关系。
- 深度学习专业化课程 5。吴恩达深入讲授递归神经网络、长短期记忆网络及其应用,如触发词检测!
- Udacity 自然语言纳米学位:如果你想遵循自上而下的方法,这是最好的课程之一。项目包括:情感分析,建立一个 ASR(自动语音识别)系统!
书籍:
- 自然语言处理在行动:我正在阅读它,对我来说看起来很有希望
项目:
- Tensorflow 问答:这个比赛的目标是预测关于维基百科文章的真实问题的简短和详细回答。
- Quora 不真诚问题分类:看起来与之前的比赛相似,但实际上是为了识别和标记不真诚的问题。
- Tensorflow 语音识别(tensor flow Speech Recognition):如果你想建立自动语音识别模型,这个比赛是必不可少的。这场比赛包括 65,000 个由 30 个短词组成的一秒钟长的话语,由成千上万不同的人完成。在这场比赛中,你的挑战是使用语音命令数据集来构建一个能够理解简单语音命令的算法。
资源
- 拥抱脸:所有 NLP 相关任务的最佳库之一。在您开始实现任何定制模型之前,一定要检查他们是否已经为您完成了。
- Super Duper NLP repo :包含该领域最常见问题的笔记本。
结论
这篇文章旨在指导你如何开始深度学习/计算机视觉/自然语言处理,如果你目前不在数据科学领域工作,但打算转行到数据科学职位,你可以如何向未来的雇主展示你的投资组合。
请注意,在一个月内学习这些技术和进一步的子领域没有捷径,需要大量的时间和努力,最重要的是需要大量的自我决定。现在的问题是:
“你有这种能力吗?”
如果是,那么你拥有世界上所有的资源,如果不是,那么甚至不是世界上所有的资源都能帮到你。
关于我
我叫 Harveen,目前在 ThoughWorks 公司担任数据科学家。我正在设计像印地语,马拉地语,泰卢固语,卡纳达语等印度语自动端到端语音识别系统的状态!
请随时在 LinkedIn 上与我联系!
谢谢!请随时评论任何进一步的资源。我将对它们进行审查,并将其添加到本文中。感谢阅读!
使用 R 进行客户流失预测,并比较不同的客户流失预测模型
使用 GLM、决策树和随机森林来预测流失,并比较模型的准确性和 AUC 值
什么是客户流失?
当应用于客户群时,流失率是指在给定时间段内离开供应商的合同客户或订户的比例。(维基百科)
为什么客户流失预测很重要?
流失率直接关系到公司的盈利能力。一些人对顾客行为了解得越多,就能获得越多的利润。这也有助于识别和改进客户服务不足的领域。
获取和处理数据
数据是从 IBM 收集的。首先加载所需的库和数据,并查看数据。
library(tidyverse)
library(caret)
library(repr)
library(caTools)
library(rpart)
library(rpart.plot)
library(ggpubr)# input the data and take a look on the variables
data <- read.csv("telco.csv")
glimpse(data)data <- data[complete.cases(data),] # removing na's
图 1:看一下数据
关于数据:
- 在这个数据中,所有的行代表不同的客户,每一列代表他们的属性。
- “流失”列表示客户在上个月离开。
- 客户订购的服务—电话、多条线路、互联网、在线安全、在线备份、设备保护、技术支持以及流媒体电视和电影。
- 每个客户的账户信息——合同、支付方式、无纸化账单、每月费用和总费用。
- 人口统计信息——性别、年龄范围,以及他们是否有伴侣和家属
数据角力:
- 为了方便起见,像“没有互联网服务”和“没有电话服务”这样的术语应该改为“没有”。
data <- data.frame(lapply(data, function(x) {
gsub("No internet service", "No", x)}))data <- data.frame(lapply(data, function(x) {
gsub("No phone service", "No", x)}))
2.SeniorCitizen 用 1 和 0 回答,分别改为“是”或“否”。
data$SeniorCitizen <- as.factor(ifelse(data$SeniorCitizen==1, 'YES', 'NO'))
3.将 double 类型变量转换为 numeric 类型,并将它们作为数据框存储在变量中。
num_columns <- c("tenure", "MonthlyCharges", "TotalCharges")
data[num_columns] <- sapply(data[num_columns], as.numeric)data_int <- data[,c("tenure", "MonthlyCharges", "TotalCharges")]
data_int <- data.frame(scale(data_int))
4.任期以月为单位。我们应该把它换算成年。
data <- mutate(data, tenure_year = tenure)data$tenure_year[data$tenure_year >=0 & data$tenure_year <= 12] <- '0-1 year'
data$tenure_year[data$tenure_year > 12 & data$tenure_year <= 24] <- '1-2 years'
data$tenure_year[data$tenure_year > 24 & data$tenure_year <= 36] <- '2-3 years'
data$tenure_year[data$tenure_year > 36 & data$tenure_year <= 48] <- '3-4 years'
data$tenure_year[data$tenure_year > 48 & data$tenure_year <= 60] <- '4-5 years'
data$tenure_year[data$tenure_year > 60 & data$tenure_year <= 72] <- '5-6 years'data$tenure_year <- as.factor(data$tenure_year)
5.准备用于分析的最终数据,排除我们在整个分析过程中不需要的选定变量。
data$tenure_year <- as.factor(data$tenure_year)data_req <- data[,-c(1,6,19,20)]
x <- data.frame(sapply(data_req,function(x) data.frame(model.matrix(~x-1,data =data_req))[,-1]))x <- na.omit(x) # omit the NA's
data_int <- na.omit(data_int) # omit the NA'sdata_final <- cbind(x, data_int)
探索性分析
- 数字变量之间的相关图:
nv <- sapply(data_int, is.numeric)
cormat <- cor(data_int[,nv])
ggcorrplot::ggcorrplot(cormat, title = "Correlation of Numeric Variables")
图 2:数值变量的相关图
2.流失率表明上个月大约有 26.58%的客户离开。
churn <- data %>%
group_by(Churn) %>%
summarise(Count = n())%>%
mutate(percentage = prop.table(Count)*100)
ggplot(churn, aes(reorder(Churn, -percentage), percentage), fill = Churn)+
geom_col(fill = c("green", "red"))+
geom_text(aes(label = sprintf("%.2f%%", percentage)))+
xlab("Churn") +
ylab("Percent")+
ggtitle("Churn Percentage")
图 3:流失率
3.条形图显示分类变量中的流失率。
fig1 <- ggarrange(ggplot(data, aes(x=gender,fill=Churn))+ geom_bar() ,
ggplot(data, aes(x=SeniorCitizen,fill=Churn))+ geom_bar(position = 'fill'),
ggplot(data, aes(x=Partner,fill=Churn))+ geom_bar(position = 'fill'),
ggplot(data, aes(x=Dependents,fill=Churn))+ geom_bar(position = 'fill'),
ggplot(data, aes(x=PhoneService,fill=Churn))+ geom_bar(position = 'fill'),
ggplot(data, aes(x=MultipleLines,fill=Churn))+ geom_bar(position = 'fill'),
ggplot(data, aes(x=InternetService,fill=Churn))+ geom_bar(position = 'fill'),
ggplot(data, aes(x=OnlineSecurity,fill=Churn))+ geom_bar(position = 'fill'),
ggplot(data, aes(x=OnlineBackup,fill=Churn))+ geom_bar(position = 'fill'),
ggplot(data, aes(x=DeviceProtection,fill=Churn))+ geom_bar(position = 'fill'),
ggplot(data, aes(x=TechSupport,fill=Churn))+ geom_bar(position = 'fill'),
ggplot(data, aes(x=StreamingTV,fill=Churn))+ geom_bar(position = 'fill'),
ggplot(data, aes(x=StreamingMovies,fill=Churn))+
geom_bar(position = 'fill'),
ggplot(data, aes(x=Contract,fill=Churn))+
geom_bar(position = 'fill'),
ggplot(data, aes(x=PaperlessBilling,fill=Churn))+
geom_bar(position = 'fill'),
ggplot(data, aes(x=PaymentMethod,fill=Churn))+
geom_bar(position = 'fill')+theme_bw()+
rremove("x.text"),
ncol = 3, nrow = 6,
common.legend = TRUE, legend = "bottom")
annotate_figure(fig1, bottom = text_grob("Churn Percentage in categorical variables", col = "blue", face = "bold", size = 14))
图 4:分类变量中的流失百分比
4.以数字变量显示流失百分比的条形图。
fig2 <- ggarrange(
ggplot(data, aes(y= tenure, x = "", fill = Churn))
+geom_boxplot() + xlab(" "),
ggplot(data, aes(y= MonthlyCharges, x = "", fill = Churn)) +geom_boxplot() + xlab(" "),
ggplot(data, aes(y= TotalCharges, x = "", fill = Churn))
+geom_boxplot() + xlab(" "),
rremove("x.text"),
ncol = 2, nrow = 2, common.legend = TRUE, legend = "bottom")annotate_figure(fig2, bottom = text_grob("Churn Percentage in numeric variables", col = "red", face = "bold", size = 14))
图 5:数字变量中的流失率
不同模型的分析
逻辑回归
- 将数据拆分为训练集和测试集
set.seed(123)
split <- sample.split(data_final$Churn, SplitRatio = 0.70)
train <- data_final[split,]
test <- data_final[!(split),]
2.计算基线精度
prop.table(table(train$Churn))
图 6:基线精度
3.使用 glm()函数拟合模型
glm <- glm(Churn ~., data = train, family = "binomial")
summary(glm)
图 7:来自 GLM 的总结
4.计量精度
pred <- predict(glm, data = train, type = "response")# confusion matrix on training setglmtab1 <- table(train$Churn, pred >= 0.5)
acc_glm_train <- (3275+708)/nrow(train)# observations on the test set
predtest <- predict(glm, newdata = test, type = "response")
glmtab2 <- table(test$Churn, predtest >= 0.5)
acc_glm_test <- (1382+307)/nrow(test)
精度= 0.80
5.重要变量
图 8:来自 GLM 的重要变量
随机森林
- 拟合模型
fit_rf <- randomForest(Churn ~ ., data=train, proximity=FALSE,importance = FALSE)
fit_rf
图 9:来自 RF 的摘要
2.计算精度
predrf <- predict(fit_rf, data = "train", type = "response")rftab <- table(predrf, train$Churn)
acc_rf_train <- (3248+694)/nrow(train)
acc_rf_train
精度= 0.80
3.误差和重要变量图
plot(fit_rf)
varImpPlot(rf)
图 10:RF 方法的误差和重要变量图
决策树
- 符合模型
rpart <- rpart(Churn ~. , data = train, method = "class", control = rpart.control((cp = 0.05)))
summary(rpart)
图 11:决策树摘要的一部分
2.计算精度
rpred <- predict(rpart, data = train, type = "class")
dtab1 <- table(rpred, train$Churn)
acc_rpart_train <- (3380+522)/nrow(train) rpredt <- predict(rpart, newdata = test, type = "class")
dtab2 <- table(rpredt, test$Churn)
acc_rpredt_test <- (1435+218)/nrow(test)
精度= 0.78
3.重要变量
图 12:来自 DT 的重要变量。
所有三款车型的 AUC
本代码参考: rstudio-pubs 。
library(pROC)glm.roc <- roc(response = test$Churn, predictor = as.numeric(predtest))
rpart.roc <- roc(response = train$Churn, predictor = as.numeric(predrf))
rf.roc <- roc(response = test$Churn, predictor = as.numeric(rpredt))plot(glm.roc, legacy.axes = TRUE, print.auc.y = 1.0, print.auc = TRUE)
plot(rpart.roc, col = "blue", add = TRUE, print.auc.y = 0.65, print.auc = TRUE)
plot(rf.roc, col = "red" , add = TRUE, print.auc.y = 0.85, print.auc = TRUE)legend("bottom", c("Random Forest", "Decision Tree", "Logistic"),
lty = c(1,1), lwd = c(2, 2), col = c("red", "blue", "black"), cex = 0.75)
图 13:这些模型的 AUC
结论:
- 比较准确性和 AUC 值,逻辑模型比随机森林和决策树更好地预测该特定数据集中的流失。
- 任期、合同、无纸账单、互联网服务是最重要的特征。
- 一些特征如性别、伴侣等对客户流失没有影响。
其他故事: