R 将数字向量的每个元素与;“最相似”;因子向量的水平
我有一个数值向量:R 将数字向量的每个元素与;“最相似”;因子向量的水平,r,vector,match,R,Vector,Match,我有一个数值向量: x <-c(-18.695, -18.695, 19.477, 0.000, 55.000, 19.477, -18.695, 48.476, 55.000, 37.798, -18.695, 19.477, 37.798, 0.000, -18.695) 我需要构建一个新的因子向量z,其长度与x相同,但具有y中列出的级别,并且使得z,z[I]的第I个元素是y中与x,x[I]对应元素“最相似”的元素。换言之: z <-factor(c("IV-18_7", "I
x <-c(-18.695, -18.695, 19.477, 0.000, 55.000, 19.477, -18.695, 48.476, 55.000, 37.798, -18.695, 19.477, 37.798, 0.000, -18.695)
我需要构建一个新的因子向量z
,其长度与x
相同,但具有y
中列出的级别,并且使得z
,z[I]
的第I个元素是y
中与x
,x[I]
对应元素“最相似”的元素。换言之:
z <-factor(c("IV-18_7", "IV-18_7", "IV19_5", "IV00", "IV55", "IV19_5", "IV-18_7", "IV48_5", "IV55", "IV37_8", "IV-18_7", "IV19_5", "IV37_8", "IV00", "IV-18_7"), levels = y)
z这里有一个解决方案,我首先在x2中猜测正确的格式,然后使用编辑距离来找到最接近的匹配
x <-c(18.695, -18.695, 19.477, 0.000, 55.000, 19.477, -18.695, 48.476, 55.000, 37.798, -18.695, 19.477, 37.798, 0.000, -18.695)
y <- c("IV-18_7", "IV00", "IV00orig", "IV19_5", "IV37_8", "IV37_8_yp", "IV48_5", "IV48_5_yp", "IV55")
x2 <- rep('', length(x))
for (i in 1:length(x)) {
x2[i] <- paste0('IV', floor(x[i]), '_', 10 * round(x[i] - floor(x[i]), 1))
}
# define edit distance and find the closest match
dist <- adist(x2, y)
z <- rep('', length(x))
for (i in 1:length(x)) {
m <- min(dist[i, ])
w <- which(dist[i, ] == m)
z[i] <- y[w]
}
x这里有一个解决方案,我首先在x2中猜测正确的格式,然后使用编辑距离来找到最接近的匹配
x <-c(18.695, -18.695, 19.477, 0.000, 55.000, 19.477, -18.695, 48.476, 55.000, 37.798, -18.695, 19.477, 37.798, 0.000, -18.695)
y <- c("IV-18_7", "IV00", "IV00orig", "IV19_5", "IV37_8", "IV37_8_yp", "IV48_5", "IV48_5_yp", "IV55")
x2 <- rep('', length(x))
for (i in 1:length(x)) {
x2[i] <- paste0('IV', floor(x[i]), '_', 10 * round(x[i] - floor(x[i]), 1))
}
# define edit distance and find the closest match
dist <- adist(x2, y)
z <- rep('', length(x))
for (i in 1:length(x)) {
m <- min(dist[i, ])
w <- which(dist[i, ] == m)
z[i] <- y[w]
}
x这是一个单行程序,应该可以让您非常接近
paste0("IV", sub(".", "_", sub("\\.0$", "", sprintf("%04.1f", round(x, 1))), fixed=TRUE))
[1] "IV18_7" "IV-18_7" "IV19_5" "IV00" "IV55" "IV19_5" "IV-18_7" "IV48_5" "IV55"
[10] "IV37_8" "IV-18_7" "IV19_5" "IV37_8" "IV00" "IV-18_7"
它的工作原理如下。原始向量x四舍五入到第一个有效数字。然后,如果字符数小于4,则格式为“%04.1f”的sprintf
将结果填充为前导“0”。该结果被馈送至sub
,该sub会删除任何后跟“0”的点(句点)实例。最后,外部的子部分
将点替换为下划线。这里有一条单行线,应该可以让您非常接近
paste0("IV", sub(".", "_", sub("\\.0$", "", sprintf("%04.1f", round(x, 1))), fixed=TRUE))
[1] "IV18_7" "IV-18_7" "IV19_5" "IV00" "IV55" "IV19_5" "IV-18_7" "IV48_5" "IV55"
[10] "IV37_8" "IV-18_7" "IV19_5" "IV37_8" "IV00" "IV-18_7"
它的工作原理如下。原始向量x四舍五入到第一个有效数字。然后,如果字符数小于4,则格式为“%04.1f”的sprintf
将结果填充为前导“0”。该结果被馈送至sub
,该sub会删除任何后跟“0”的点(句点)实例。最后,外部的sub
用下划线替换点。既然将x
(忽略符号)的整数部分与y
中的前两位匹配就足够了,我们可以使用sub
从y
中提取前两位,并匹配地板(abs(x))
将其作为数字:
x.int <- floor(abs(x))
y.2digits <- as.numeric(sub('.*?([0-9]{2}).*', '\\1', y))
z <- factor(y[match(x.int,y.2digits)],levels=y)
## [1] IV-18_7 IV-18_7 IV19_5 IV00 IV55 IV19_5 IV-18_7 IV48_5 IV55 IV37_8 IV-18_7
##[12] IV19_5 IV37_8 IV00 IV-18_7
##Levels: IV-18_7 IV00 IV00orig IV19_5 IV37_8 IV37_8_yp IV48_5 IV48_5_yp IV55
x.int既然将x
(忽略符号)的整数部分匹配到y
中的前两位数字就足够了,我们可以使用sub
从y
中提取前两位数字,并将地板(abs(x))
匹配为数字:
x.int <- floor(abs(x))
y.2digits <- as.numeric(sub('.*?([0-9]{2}).*', '\\1', y))
z <- factor(y[match(x.int,y.2digits)],levels=y)
## [1] IV-18_7 IV-18_7 IV19_5 IV00 IV55 IV19_5 IV-18_7 IV48_5 IV55 IV37_8 IV-18_7
##[12] IV19_5 IV37_8 IV00 IV-18_7
##Levels: IV-18_7 IV00 IV00orig IV19_5 IV37_8 IV37_8_yp IV48_5 IV48_5_yp IV55
x.int这将使您非常接近您的示例:paste0(“IV”,gsub(“.”,“\uu”),gsub(\\.0$”,“”,sprintf(“%04.1f”),round(x,1)),fixed=TRUE))
它看起来不仅非常接近,而且非常准确!谢谢你为什么不把它写下来作为一个答案,并解释一下单件作品的作用呢?(对我来说)理解一行程序是很困难的。这会让你非常接近你的例子:paste0(“IV”,gsub(“.”,“\uu”),gsub(\\.0$”,“,”,sprintf(“%04.1f”,round(x,1)),fixed=TRUE))
它看起来不仅非常接近,而且非常到位!谢谢你为什么不把它写下来作为一个答案,并解释一下单件作品的作用呢?(对我来说)理解一行程序很困难。它很有效!我不知道adist的事。在我的环境中,代码运行时带有一些警告(在z[i]中),它可以工作!我不知道adist
。在我的环境中,代码运行时带有一些警告(在z[i]中)