match function in R for version 4.0.4

Viewed 65

I have 2 large datasets. One is DB as the database and one is the raw for my own data :

just a sample of the 2 dataframes:

DB:
| rel.genes |        code           | description |
|    fla    | VFG002519(gbYP_109887)| sahashdkjas |
|    un     | YP_105432             | sashjkas    |

raw:
| species |   sacver | qacver |
|   saa   | YP_109887| 122134 |
|   saa   | YP_105432| 42234  |

I want to match the sacver data of the raw to the code column of the DB dataframe. If the sacver is found in one row of the code, it should give the output of the corresponding "rel.genes" from the DB dataframe to a new column in the raw dataframe. I used to this easily with this code:

raw$genes <- DB$rel.genes[match(raw$sacver,DB$code)]

It should produce this table:

| species |  sacver  | qacver | genes |
|    saa  | YP_109887| 123214 |  fla  |
|    saa  | YP_105432| 42234  |   un  |

Now that I updated my R to version 4.0.4, this code doesn't work anymore. Instead of having the rel.genes as the output, it just has "NA" for all rows of the new genes column.

What should I change with my code?

1 Answers

match is looking for exact matches, and "VFG002519(gbYP_109887)" != "YP_109887". If you want partial matching, then I suggest fuzzyjoin:

fuzzyjoin::regex_right_join(DB, raw, by = c("code" = "sacver"))
#   rel.genes                   code description species    sacver qacver
# 1       fla VFG002519(gbYP_109887) sahashdkjas     saa YP_109887 122134
# 2        un              YP_105432    sashjkas     saa YP_105432  42234

The risk of this is partial matches. For example, if there exists raw$sacver with just YP_10988 (no 7), then it would match. This would result in either multiple matches for a row or at least a match where none should be. For example,

raw2 <- rbind(raw, data.frame(species = "saa", sacver = "YP_10988", qacver = 122135L))
raw2
#   species    sacver qacver
# 1     saa YP_109887 122134
# 2     saa YP_105432  42234
# 3     saa  YP_10988 122135

fuzzyjoin::regex_right_join(DB, raw2, by = c("code" = "sacver"))
#   rel.genes                   code description species    sacver qacver
# 1       fla VFG002519(gbYP_109887) sahashdkjas     saa YP_109887 122134
# 2        un              YP_105432    sashjkas     saa YP_105432  42234
# 3       fla VFG002519(gbYP_109887) sahashdkjas     saa  YP_10988 122135

The third row is a double-match (notice 122135, the new qacver I added).

To mitigate this risk, it will help to refine raw (which contains the "pattern" of the regex join) to include regex "word boundaries":

raw2$sacver_ptn <- paste0("\\b", raw2$sacver, "\\b")
raw2
#   species    sacver qacver      sacver_ptn
# 1     saa YP_109887 122134 \\bYP_109887\\b
# 2     saa YP_105432  42234 \\bYP_105432\\b
# 3     saa  YP_10988 122135  \\bYP_10988\\b

fuzzyjoin::regex_right_join(DB, raw2, by = c("code" = "sacver_ptn"))
#   rel.genes      code description species    sacver qacver      sacver_ptn
# 1      <NA>      <NA>        <NA>     saa YP_109887 122134 \\bYP_109887\\b
# 2        un YP_105432    sashjkas     saa YP_105432  42234 \\bYP_105432\\b
# 3      <NA>      <NA>        <NA>     saa  YP_10988 122135  \\bYP_10988\\b

Unfortunately, in your example, you have gbYP_109887, where the gb does not trigger a word-boundary like we would like. For that, I'll relax the boundaries to be on the number side:

raw2$sacver_ptn <- paste0(raw2$sacver, "\\b")
raw2
#   species    sacver qacver   sacver_ptn
# 1     saa YP_109887 122134 YP_109887\\b
# 2     saa YP_105432  42234 YP_105432\\b
# 3     saa  YP_10988 122135  YP_10988\\b

fuzzyjoin::regex_right_join(DB, raw2, by = c("code" = "sacver_ptn"))
#   rel.genes                   code description species    sacver qacver   sacver_ptn
# 1       fla VFG002519(gbYP_109887) sahashdkjas     saa YP_109887 122134 YP_109887\\b
# 2        un              YP_105432    sashjkas     saa YP_105432  42234 YP_105432\\b
# 3      <NA>                   <NA>        <NA>     saa  YP_10988 122135  YP_10988\\b

In this case, my new YP_10988 matched none of the DB entries, so it has nothing in rel.genes.

Related