将数字向量的每个元素与因子向量

时间:2016-11-15 13:18:42

标签: 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)

和一个因子向量,其从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}},zz[i]yx的对应元素中“最相似”的元素。换句话说:

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中高效编码,你能帮助我吗?

3 个答案:

答案 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来提取前两位数字从ymatch 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