R软件K近邻算法函数代码解释


##########算法理解##########
备注:
1.scale = T :如果数据在找到最近邻居之前进行缩放(默认为t),则进行布尔设置。

2.distData可选地,您可以在这里指定一个包含应该用来查找邻居的数据集的数据框。
在测试集中填写NA值时,这是有用的,您应该只使用训练集中的信息。
这默认为NULL,这意味着将在数据中搜索邻居

function (data, k = 10, scale = T, meth = "weighAvg", distData = NULL)
{
n <- nrow(data) #计算数据data的行数n
if (!is.null(distData)) { #如果distdata不是默认值NULL(注意!),那么变量distInit等于行数n+1
distInit <- n + 1
data <- rbind(data, distData) #rbind是将数据集根据行进行合并,就是自动往下面顺延组合
}
else distInit <- 1 #否则变量distInit等于1
N <- nrow(data) #记N为新data的行数
ncol <- ncol(data) #记ncol为新data的列数
nomAttrs <- rep(F, ncol) #nomattrs 就是生成一个向量,元素是FALSE,个数是ncol个(data列数个)
#seq(ncol)就是生成了1,2,3...ncol,一组连续的向量
for (i in seq(ncol)) nomAttrs[i] <- is.factor(data[, i])#判断data中每列变量类型是否为factor的变量列,
#is.factor返回值为逻辑值,此时nomattrs里也是逻辑值,TRUE对应的是data中列为factor类型的列,false则不是..
nomAttrs <- which(nomAttrs) #选出True即data的每列中是factor类型的列数,nomAttrs为一组数值
hasNom <- length(nomAttrs) #得出factor类型的列的个数
contAttrs <- setdiff(seq(ncol), nomAttrs) #setdiff(x,y)求向量x与向量y中不同的元素(只取x中不同的元素)
#contAttrs实际上就是剔除factor类别列后,剩下的列序号
dm <- data #将data赋给dm

# scale函数是将一组数进行处理,
# 默认情况下是将一组数的每个数都减去这组数的平均值后再除以这组数的均方根。
# 数据中心化和标准化的意义是一样的,为了消除量纲对数据结构的影响。
if (scale)
dm[, contAttrs] <- scale(dm[, contAttrs]) #对data的数值类型列中心化
if (hasNom)
for (i in nomAttrs) dm[, i] <- as.integer(dm[, i]) #对factor类型列的变量强制为整数型
#举例as.integer(),如果原来某列中元素为spring,summer,...等等factor类型,
#转换为整数类型后,变成了1234

#在 R 里面 numeric 类型包含了很多子类型,其中最常见的就是 double 和 integer,
#但因为最常用的是 double, 除非你特别标明是 integer (用 as.integer等方式), 系统都会认为是 double.

dm <- as.matrix(dm) #处理完后,将dm变为矩阵,此时dm中原来为factor类型的部分 也成了数值
nas <- which(!complete.cases(dm)) #nas为dm中有缺失的部分,整行目的:找出缺失的行数

if (!is.null(distData)) #如果distdata不是null,
tgt.nas <- nas[nas <= n] #t

gt.nas 等于nas(缺失行数)[提取缺失行数小于等于data行数的行]
else tgt.nas <- nas #如果distdata是null,直接 tgt.nas <- nas,也就是说如果distData是NULL,会认为我只使用训练集中的信息。

if (length(tgt.nas) == 0) ##没有缺失变量,停止因为没必要做其他事
warning("No case has missing values. Stopping as there is nothing to do.")

xcomplete <- dm[setdiff(distInit:N, nas), ]
#setdiff(distInit:N, nas)为删去缺失的行,xcomplete为完整观测的行

if (nrow(xcomplete) < k) #如果xcomplete的行数小于K,返回“没有足够完整的计算邻居的案例”
stop("Not sufficient complete cases for computing neighbors.")

for (i in tgt.nas) { #在i到tgt.nas(缺失的行数)的行数中
tgtAs <- which(is.na(dm[i, ])) #在dm中的观测缺失每一行,确定是哪列的变量缺失,赋给tgtAs
dist <- scale(xcomplete, dm[i, ], FALSE) #?是否理解为:xcomplete每列都减去缺失列的中心值
#scale(x, center = TRUE, scale = TRUE)
#如果center是一个长度等于x列数的数值向量,那么x的每一列都有从中心减去的相应值,
#如果scale是真的,那么缩放是通过将x的(中心)列除以它们的标准偏差,如果为false,则不进行缩放。

xnom <- setdiff(nomAttrs, tgtAs) #nomAttrs为数据集data原分类变量列数,tgtAs存在缺失的列数
if (length(xnom))
dist[, xnom] <- ifelse(dist[, xnom] > 0, 1, dist[, xnom]) #dist[, xnom]大于0,赋值1反之,输出原值
dist <- dist[, -tgtAs] #对dist去掉缺失列
dist <- sqrt(drop(dist^2 %*% rep(1, ncol(dist))))
#计算dist的平方与全1向量的乘法(矩阵乘法),drop()删除只有一个级别的数组的维数,再开根号
ks <- order(dist)[seq(k)]#对dist排序,取出1,2,3,...10(按照距离的递增关系进行排序,取最小距离的几个点)
for (j in tgtAs) if (meth == "median") #j在dm所有缺失的列数中,(如果设置的meth == "median")
#centralValue函数,如果变量是数值,它返回给定样本的中位数,
#如果它是一个因素,它返回模式。(见代码样例)
data[i, j] <- centralValue(data[setdiff(distInit:N,nas), j][ks])#(如果设置的meth == "median")对缺失值返回10最近个元素组成的的样本的中位数
#setdiff(distInit:N,nas)为去掉缺失的行
else data[i, j] <- centralValue(data[setdiff(distInit:N,nas), j][ks], exp(-dist[ks]))
#centralValue(x, ws = NULL)
#(如果不是设置的meth == "median",,则有一个ws=exp(-dist[ks]为权重向量,加权的

}
data[1:n, ]
}



相关文档
最新文档