R语⾔rank函数详细解析
1.rank函数是什么
2.rank函数使⽤情景
⽐如,在100⽶赛跑中,甲⼄丙三⼈的成绩为6.8s, 8.1s, 7.2s,那么⽤rank函数排序获得名次:
> rank(t <- c(6.8, 8.1, 7.2))
[1] 1 3 2
再如,甲⼄丙三⼈考试得分为74,92,85,⽤同样⽅法取得名次会适得其反。当然,我们可以认为执⾏
> rank(-(s <- c(74, 92, 85)))
[1] 3 1 2
可以达到⽬的,但这并未改变rank函数的排序机制。
3.rank函数排序类型
rank(x, na.last = TRUE,
> t <- c(4, NaN, 4, 7, 8, 2, NaN, 9, 9, 7, NaN, 5, 2, 2, 1)
#同时对相应元素做好标记
> names(t) <- letters[1 : length(t)]
通过以上⽅法进⾏排序,得出
Result
a b c d e f g h i j k l m n o
original4NaN4782NaN997NaN5221
average 5.513.0 5.58.510.0 3.014.011.511.58.515.07.0 3.0 3.0 1.0
first513681021411129157341
random (1)613591021411128157341
random (2)513681021411129157431
max613691041412129157441
min513581021411118157221
我们发现,标签"b","g","k"的次序并未发⽣改变,可推断hod作⽤在于处理⾮缺失值的顺序。
不妨参考rank的实现代码
function (x, na.last = TRUE, hod = c("average", "first",
"random", "max", "min"))
{
nas <- is.na(x) #得到与x相同长度的boolean型数组,⽤来标记相应位是否为缺失值
nm <- names(x) #获取数组中元素所对应的标签
#names函数暗⽰了该⽅法的设计初衷是对⼀维数组即列向量进⾏排序,虽然x为矩阵也会得出结果,但nm的作⽤已经失效,结果不具有意义
if (is.factor(x))
x <- as.integer(x) #若x为因⼦,则对元素"归类",并按"类的⼤⼩"进⾏整数元素编码,具体请见[说明1]
x <- x[!nas] #剔除x中的缺失值
#average\min\max采⽤了相应的.Internal(rank(x, length(x), hod)),具体请见[说明2]
#first采⽤了sort.list(sort.list(x)),具体请见[说明3]
#random采⽤了sort.list(order(x, stats::runif(sum(!nas)))),具体请见[说明4]
y <- hod, average = , min = , max = .Internal(rank(x,
length(x), hod)), first = sort.list(sort.list(x)),
random = sort.list(order(x, stats::runif(sum(!nas)))))
#下⾯是补全缺失值的次序的⽅法
#na.last = "keep",不处理缺失值,na.last = TRUE,后排序缺失值,na.last = FALSE,先排序缺失值。
if (!is.na(na.last) && any(nas)) {
yy <- NA
NAkeep <- (na.last == "keep")
if (NAkeep || na.last) {
yy[!nas] <- y
if (!NAkeep)
yy[nas] <- (length(y) + 1L):length(yy)
}
else {
len <- sum(nas)
yy[!nas] <- y + len
yy[nas] <- seq_len(len)
}
y <- yy
names(y) <- nm
}
else names(y) <- nm[!nas]
y
}
[说明1] 关于因⼦转整数
> f <- c('Ba', 'BA', 'b', 'A', 'A', 'b', 'Ba', 'Bac', NaN, NaN)
> fac <- factor(colour)
> as.integer(fac)
[1] 3 4 2 1 1 2 3 5 6 6
由此可见: (1) 因⼦会作为字符串进⾏机械⽐较,排出次序。(2) 因⼦中任意两个缺失值地位(⼤⼩)相同。
实际问题中,因⼦为⼈为设定,故采⽤有序因⼦(ordered factor),消除机械转换的⼲扰。
> qulity <- c('good','soso','good','soso','bad','good','bad')
> names(qulity) <- c('day1','day2','day3','day4','day5','day6','day7')
> q <- factor(qulity, levels = c('bad','soso','good'), labels = c('bad', 'soso', 'good'), order = TRUE)
> rank(q)
day1 day2 day3 day4 day5 day6 day7
6.0 3.5 6.0 3.5 1.5 6.0 1.5
[说明2] "average", "max", "min" 排序
> t
a b c d e f g h i j k l m n o
4 NaN 4 7 8 2 NaN 9 9 7 NaN
5 2 2 1
> rank(t, na.last = "keep", hod = "first")
a b c d e f g h i j k l m n o
5 NA
6 8 10 2 NA 11 12 9 NA
7 3 4 1
> rank(t, na.last = "keep", hod = "average")
a b c d e f g h i j k l m n o
5.5 NA 5.5 8.5 10.0 3.0 NA 11.5 11.5 8.5 NA 7.0 3.0 3.0 1.0
可以将"average"排序理解为先对数据进⾏"first"排序,即全部元素都有唯⼀且不同的次序。
如f, m, n 得分相同,但可按先后次序排成2, 3, 4, 但是f, m, n属于同⼀体,故可以取该体中的平均⽔平作为次序,使得分相同的元素地位相当。
故不难理解"max"排序是体中的元素全部取中最好的⽔平,这也是普遍采⽤的“并列排名”⽅法;
"min"排序是体中的元素全部取体中最差的⽔平,这样增⼤了不同等级的顺序差异。
[说明3] first = sort.list(sort.list(x))
对序列先按⼤⼩排序,⼤⼩相同的元素,从头⾄尾由⼩到⼤排序。
> x
a c d e f h i j l m n o
4 4 7 8 2 9 9 7
5 2 2 1
> sort.list(sort.list(x))
[1] 5 6 8 10 2 11 12 9 7 3 4 1
[说明4] random = sort.list(order(x, stats::runif(sum(!nas))))
weight = stats::runif(sum(!nas)) 为每个已知元素⽣成0-1之间随机数,作为“权重”序列weight
sort.list(order(x, weigth)) 依据随机的“权重”决定得分相同的元素的次序
不妨⼈为参与权重设计
a c d e f h i j l m n o
4 4 7 8 2 9 9 7
5 2 2 1
> weight = c(0.45, 0.55, 0.1, 0.1, 0.1, 0.55, 0.45, 0.1, 0.1, 0.3, 0.1, 0.1);
> sort.list(order(x,weight))
[1] 5 6 8 10 2 12 11 9 7 4 3 1
不难发现,a, c 得分均为4,但w(a) = 0.45 < w(c) = 0.55, 遵照⼩号在前,a 排在c 前⾯。h, j 刚好相反w(h) = 0.55 > w(j) = 0.45, j 排在h 前⾯。
d, j 得分,“权重”均相同,故按之前从头到尾递增顺序排列。
f, m, n 得分均为2, w(f) = w(n) = 0.1 < w(m) = 0.3, 排序结果为f < n < m, 由此可见,“权重”优先于“前后顺序”,这样做使得排序更加随机化,若序列存在⼤量得分相同的元素,⼀定程度克服了“前⼩后⼤”规则的约束,使排序结果更随机。
以上仅为说明随机排序的机制,实际应⽤中只能确定⼩数在前⼤数在后,并不能解释相同的数之间的顺序。
4.rank函数⼩结
rank(x, na.last = TRUE,
(1) rank 函数是对⼀维度数组、向量x 进⾏排序。若x 为数值,则按照⼩数在线⼤数在后的原则进⾏排序,若x 为因⼦,则应参考[说明1]进⾏顺序因⼦设计。P.S. 实际情况中,存在⼤量⽤⼆维表格描述的数据,⽐如⾏表⽰地点列表⽰时间的统计表,若进⾏排序,应先通过字符拼接的⼿段将表格转化为⼀维的向量,否则结果将失去意义。
rank函数怎么用(2) rank 将数据分为确定值与缺失值两种。缺失值可按先后排在确定值之间(na.last = FALSE), 也可排在之后(na.last = TRUE), 也可保留,不参与排序(na.last = "keep").
(3) "first" 是最基本的排序,⼩数在前⼤数在后,相同元素先者在前后者在后。
"max" 是相同元素都取该组中最好的⽔平,即通常所讲的并列排序。
"min" 是相同元素都取该组中最差的⽔平,可以增⼤序列的等级差异。
"average" 是相同元素都取该组中的平均⽔平,该⽔平可能是个⼩数。
"random" 是相同元素随机编排次序,避免了“先到先得”,“权重”优于“先后顺序”的机制增⼤了随机的程度。
[1]Returns the sample ranks of the values in a vector. Ties (i.e., equal values) and missing values can be handled in several ways.
发布评论