【问题标题】:Associate each elements of a numeric vector to the "most similar" level of a factor vector将数值向量的每个元素与因子向量的“最相似”级别相关联
【发布时间】:2016-11-15 13:18:41
【问题描述】:

我有一个数字向量:

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 中列出的级别,并且z 的第i 个元素z[i]yxx[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)

这个例子应该让“最相似”的意思相当明显,反正想法是取一个元素x[i],然后寻找y的元素,它是通过添加一个“IV”前缀得到的,然后添加一个与x[i] 的舍入“相似”的字符串(但不幸的是,不完全相等),最后在数字部分之后没有任何后缀。我不知道如何在 R 中有效地编写代码,您能帮帮我吗?

【问题讨论】:

  • 这将使您非常接近您的示例:paste0("IV", gsub(".", "_", gsub("\\.0$", "", sprintf("%04.1f", round(x, 1))), fixed=TRUE))
  • 它看起来不仅非常接近而且就在现场!谢谢!您为什么不将其写为答案并解释单件的作用? (对我来说)很难理解单行。

标签: r vector match


【解决方案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 舍入到第一个有效数字。然后 sprintf 如果字符数小于 4,则使用“%04.1f”格式将结果填充为前导“0”。此结果将馈送到sub,它会删除任何点(句点)实例,然后是“0”。最后,外部的sub 将点替换为下划线。

【讨论】:

    【解决方案2】:

    这里有一个解决方案,我先在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]
    }
    

    【讨论】:

    • 它有效!我不知道adist。在我的环境中,代码运行时会出现一些警告 (In z[i] &lt;- y[w] : number of items to replace is not a multiple of replacement length),但除此之外,它提供了正确的解决方案。
    【解决方案3】:

    由于似乎将x 的整数部分(忽略符号)与y 中的前两位数字匹配就足够了,我们可以使用suby 和@ 中提取前两位数字987654325@ 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-21
      • 2012-09-06
      • 1970-01-01
      • 1970-01-01
      • 2021-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多