我有一个数字向量:
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)
和一个因子向量,其从levels
函数返回的级别为:
y <- c("IV-18_7", "IV00", "IV00orig", "IV19_5", "IV37_8", "IV37_8_yp", "IV48_5", "IV48_5_yp", "IV55")
我需要构建一个新的因子向量z
,其长度与x
相同,但具有y
中列出的级别,以及{i}的第i个元素{1}},z
是z[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)
,然后寻找通过添加“IV”获得的x[i]
元素“前缀,然后添加一个与y
的舍入”相似“的字符串(但不幸的是不完全相同),最后在数字部分之后没有任何后缀。我不知道如何在R中高效编码,你能帮助我吗?
答案 0 :(得分:1)
这是一个解决方案,我首先猜测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]
}
答案 1 :(得分:1)
这是一个应该让你非常接近的单行。
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
,这会丢弃任何点的实例(句号)后跟“0”。最后,外部sub
用下划线替换点。
答案 2 :(得分:1)
由于似乎将x
(忽略符号)的整数部分与y
中的前两位数匹配就足够了,我们可以使用sub
来提取前两位数字从y
和match
floor(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