r语言 - 通过一列左连接两个数据帧.如果没有返回匹配项,则通过另一列连接



我想先通过一列将一个数据帧连接到另一个数据帧,然后,如果没有匹配"我想让它通过另一列连接起来。这个问题与这个问题类似,但我试图得到一个稍微不同的输出。

以下是我的"观察">

#my df
my_plants <- data.frame(scientific_name = c("Abelmoschus esculentus",
"Abies balsamea",
"Ammophila breviligulata",
"Zigadenus glaucus"),
percent_cover = c(90, 80, 10, 60))

,这里是main list,我想从每个观察中提取一些数据。显然这是简化的。

#hypothetical database
plant_database <- data.frame(scientific_name = c("Abelmoschus esculentus",
"Abies balsamea",
"Ammophila breviligulata",
"Anticlea elegans"),
synonym = c(NA_character_,
NA_character_,
NA_character_,
"Zigadenus glaucus"),
score = c(1, 1, 2, 6))

这是一个将我的观察结果加入到主列表的函数。注意:我使用left_join是因为我想知道哪些观测值不匹配。

#joining function
joining_fun <- function(plants, database) {
database_long <- database %>%
dplyr::mutate(ID = row.names(.)) %>%
tidyr::pivot_longer(., cols = c(scientific_name, synonym),
values_to = "scientific_name")
join <- dplyr::left_join(plants, database_long, by = "scientific_name") %>% 
dplyr::select(-name)
return(join)
}

让我在这里:

joining_fun(my_plants, plant_database)
scientific_name percent_cover score ID
1  Abelmoschus esculentus            90     1  1
2          Abies balsamea            80     1  2
3 Ammophila breviligulata            10     2  3
4       Zigadenus glaucus            60     6  4

但是我想要这样的:

scientific_name           synonym           percent_cover score ID  
Abelmoschus esculentus    NA                90     1  1          
Abies balsamea            NA                80     1  2  
Ammophila breviligulata   NA                10     2  3        
Anticlea elegans          Zigadenus glaucus 60     6  4

谢谢!

  1. 使用inner_join()创建只包含scientific_name上匹配的情况的df
  2. 使用anti_join()获取匹配scientific_nameplants版本。
  3. 在这些不匹配的情况下,使用"synonym" = "scientific_name"键执行database的另一个inner_join()
  4. 再做一个anti_join()来获得在任何一列中没有匹配的情况。
  5. 最后,将所有结果绑定在一起。
library(dplyr)
# add test case with no match in either column
my_plants <- add_row(
my_plants, 
scientific_name = "Stackus overflovius", 
percent_cover = 0
)
joining_fun <- function(plants, database) {
by_sci_name <- inner_join(plants, database, by = "scientific_name")
no_sci_match <- anti_join(plants, database, by = "scientific_name")
by_syn <- inner_join(database, no_sci_match, by = c("synonym" = "scientific_name"))
no_match <- anti_join(no_sci_match, database, by = c("scientific_name" = "synonym"))
bind_rows(by_syn, by_sci_name, no_match)
}
joining_fun(my_plants, plant_database)
scientific_name           synonym score percent_cover
1        Anticlea elegans Zigadenus glaucus     6            60
2  Abelmoschus esculentus              <NA>     1            90
3          Abies balsamea              <NA>     1            80
4 Ammophila breviligulata              <NA>     2            10
5     Stackus overflovius              <NA>    NA             0