【问题标题】:How Can I vectorize this function to return an index vector?如何向量化此函数以返回索引向量?
【发布时间】:2011-01-19 15:08:29
【问题描述】:

我是 R 新手,正在尝试处理 apply 系列函数。具体来说,我正在尝试编写一个高阶函数,它将接受 2 个字符向量“host”和“guest”(不需要相同的长度)并返回一个与“host”长度相同的索引向量",生成的元素对应于它们在来宾中的索引(如果不存在,则为 NA)。

host <- c("A","B","C","D")
guest <- c("D","C","A","F")

matchIndices <- function(x,y)
{
  return(match(x,y))
}

此代码按预期返回 3:

matchIndices(host[1],guest)

这是我希望能够用简洁的应用函数(sapply?)替换的循环

for (i in 1:length(host)) 
{ idx <- matchIndices(host[i],guest); 
  cat(paste(idx,host[i],"\n",sep=";"))
}

这段代码“有效”,因为它产生了下面的输出,但我真的希望结果是一个向量,而且我预感其中一个应用函数可以解决问题。我只是纠结于如何写。非常感激任何的帮助。谢谢。

3;A; 不适用;乙; 2;C; 1;D;

【问题讨论】:

    标签: r


    【解决方案1】:
    host <- c("A","B","C","D")
    guest <- c("D","C","A","F")
    
    matchIndices <- function(x,y) {
        return(match(x,y))
    }
    

    一种(低效)方法是在host 向量上使用sapply,将guest 作为参数传入(注意您可以将其简化为sapply(host, match, guest),但这说明了处理此类问题的一般方法事情):

    > sapply(host, matchIndices, guest)
     A  B  C  D 
     3 NA  2  1
    

    但是,这可以直接使用match 完成,因为它接受向量第一个参数:

    > match(host, guest)
    [1]  3 NA  2  1
    

    如果你想要一个命名向量作为输出,

    > matched <- match(host, guest)
    > names(matched) <- host
    > matched
     A  B  C  D 
     3 NA  2  1
    

    可以封装成函数

    matchIndices2 <- function(x, y) {
        matched <- match(x, y)
        names(matched) <- x
        return(matched)
    }
    

    返回

    > matchIndices2(host, guest)
     A  B  C  D 
     3 NA  2  1
    

    如果您真的希望将名称和匹配项组合成一个字符串向量,那么:

    > paste(match(host, guest), host, sep = ";")
    [1] "3;A"  "NA;B" "2;C"  "1;D"
    

    【讨论】:

    • 你可以只做sapply(host, match, guest),不需要定义matchIndices
    • @Prasad 是的,你可以,但我离开这个就像是为了展示如何以这种方式应用用户功能。我留下它的原因是这一切都可以直接用match 完成,因为它接受向量第一个参数。请参阅我的更新答案。
    • 这太棒了。非常感谢你。 “匹配(主人,客人)”是完美的。我没有意识到它会这么紧凑。
    【解决方案2】:

    如果您想要host;guestNum 格式的输出向量,您可以使用do.callpastematch,如下所示:

    > do.call(paste, list(host, sapply(host, match, guest), sep = ';'))                                                                                     
    [1] "A;3"  "B;NA" "C;2"  "D;1" 
    

    【讨论】:

    • 正如我所说,这里根本不需要sapplymatch 接受向量第一个参数,因此我们可以将其简化为 do.call(paste, list(host, match(host, guest), sep = ';')) 但这似乎有点矫枉过正要实现 paste(match(host, guest), host, sep = ";")paste(host, match(host, guest), sep = ";") 不是吗?
    • 非常正确@Gavin,这是最简单的方法
    • 该死,你是对的。所以do.call(paste,list(host,match(host,guest),sep=";")) 会做
    • @Joris 是的,如果你喜欢阅读复杂的 R 代码 ;-) 直接调用 paste 更简单:paste(host, match(host, guest), sep = ";")
    【解决方案3】:
    sapply(host , function(x) which(guest==x))
    $A
    [1] 3
    
    $B
    integer(0)
    
    $C
    [1] 2
    
    $D
    [1] 1
    
    
    unlist(sapply(host , function(x) which(guest==x)))
    
        A C D 
        3 2 1 
    
    paste(host, sapply(host , function(x) which(guest==x)), sep=":", collapse=" ")
    [1] "A:3 B:integer(0) C:2 D:1"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多