r 中的 MATCH 函数

ana*_*nat 2 r match vlookup

有列表,第一个 (list1) 有 id,name,age 和其他 (list2,list3,..) 有 ids 和测试值(唯一)。

清单 1:

id  age name    bio-test    
1   40  danny
2   16  nora            
3   35  james
4   21  ben
Run Code Online (Sandbox Code Playgroud)

清单 2(生物测试):

id  test passed year   
1   100   yes   1
5   80    yes   n/a      
4   55    no    2
Run Code Online (Sandbox Code Playgroud)

我正在尝试将每个 id 的测试值添加到 list1(并非每个 id 都有一个测试值)。

这是代码的一部分:

for (i in 1:length(list1)) { 
list1$test1value <- list2$test[match(list1$id[i], list2$id[i]),
nomatch = NA_integer_, incomparables = NULL)] }
Run Code Online (Sandbox Code Playgroud)

但是通过 id 查找测试值,它只复制了 list2 中的第一个测试值并将其复制到 200 个单元格,其他 3000 个是 N/A。

怎么了?

Pie*_*une 6

首先,您的示例中有错别字。其次,'list1$test1value' 的赋值应该添加一个 '[i]' 以不保存每一轮。也不应该添加“[i]”,list2$id因为您要搜索整个向量以进行查找。

for (i in 1:length(list1)) { 
  list1$test1value[i] <- list2$test[match(list1$id[i], list2$id,
                             nomatch = NA_integer_, incomparables = NULL)] }
Run Code Online (Sandbox Code Playgroud)

代码有效,但这里没有任何循环的理由。您对 R 的运作方式缺乏了解。下面的代码以更快的速度完成完全相同的事情。

list1$test1value <- list2$test[match(list1$id, list2$id)]
Run Code Online (Sandbox Code Playgroud)

R 的构建使您不必握住它的手并指示它如何遍历向量的每个元素。match将自动逐个遍历每个成员,并在另一个向量中为您查找。它还将在数据集中以有序的方式分配结果。

我将其作为副本关闭,因为正如其他人所建议的那样,merge它非常适合于此。

merge(list1, list2[c("id", "test")], all.x=TRUE)
#  id age  name test
#1  1  40 danny  100
#2  2  16  nora   NA
#3  3  35 james   NA
#4  4  21   ben   55
Run Code Online (Sandbox Code Playgroud)