在一个表里有一个升序排序后的数值型字段,需要找出一个“TOP N”的位置,在此位置前数据之间的差距很小,而此位置后数据之间的差距突然变大。下面的栗子中,前面十几位的数值分别是在0.11、0.12、0.13、0.14、0.15缓慢增长,第18个数字变成了0.47,和前面的相比差距很大,此时要找到的“TOP N”就是17。
楼主暂时只根据 AI 给的建议先将就用着一个比较粗暴的方法,就是计算这串序列的差分,在一个 for 循环里,找到第一个差分值大于均值+标准差的位置。请教坛子里的小伙伴们有没撒好办法?
library(echarts4r)
data <- data.frame(rank_asc = c(1:30),
values = c(
0.116161, 0.116812, 0.1179149, 0.1187652, 0.1197417, 0.120519, 0.1208446, 0.1303933, 0.1303933, 0.1303933, 0.1336485, 0.1341733, 0.1352761, 0.1431509, 0.151769, 0.1577087, 0.1577087, 0.4789998, 0.4808422, 0.4831949, 0.488747, 0.4965138, 0.4969146, 0.4972559, 0.4993662, 0.4998289, 0.5006878, 0.5020363, 0.5024971, 0.5025391))
# 绘制折线图
data |>
e_charts(rank_asc) |>
e_line(values)
first_diff <- function(values) {
# 对一组按从小到大排序的数值计算差分
differences <- diff(values)
# 找到第一个差值大于平均值加上标准差的位置
for (i in 2:(length(differences) - 1)) {
if (differences[i] > mean(differences[1:i]) + sd(differences[1:i]) * 3) {
#cat("距离突然变大的位置是", i, "\n")
return(i)
break
}
}
}
first_diff(data$values)
本平庸程序员最后让 AI 给帮忙改成了这样,倒真是挺实用的。
first_diff <- function(values) {
differences <- diff(values)
mean_diff <- cumsum(differences) / (1:length(differences))
sd_diff <-
sqrt(cumsum((differences - mean_diff) ^ 2) / (1:length(differences)))
result <- 10 # 默认返回值
for (threshold in c(3, 2, 1)) {
for (i in 2:(length(differences) - 1)) {
if (differences[i] > mean_diff[i] + threshold * sd_diff[i]) {
if (i < 20) {
result <- i # 存储返回值,而不是直接返回
break
}
}
}
}
# 如果第一个差分值比接下来19个差分值都大,返回1
if (is.na(i) == FALSE & differences[1] > max(differences[2:20])) {
return(1)
}
return(result) # 返回存储的值
}