如何将应用族函数用于具有不同行的两个数据帧,而不是嵌套循环



我有一个大的数据帧和另一个相对较小的不同行数的数据帧,我需要匹配任何项。我想使用应用族函数来避免嵌套for循环。以下是我试图实现的,但没有使其高效的环路

下面是一个示例代码。我有两个不同行的数据帧,比如animal和rand_string。我需要根据动物数据帧中的动物列更新rand_string中"new"列的值。

animal <- c("llama", "meerkat", "coyote") %>% as.data.frame() %>% rename(animal = ".") %>%
mutate(type = "mamal") %>%
rbind(data.frame(animal = "hawk", type = "bird")) %>%
rbind(data.frame(animal = "bee", type = "insect"))
rand_string <- ids::adjective_animal(1E6, n_adjectives=1) %>% as.data.frame() %>% rename(animal = ".")
rand_string2 <- rand_string[1:50,] %>% as.data.frame() %>% rename(animal = ".") %>% mutate(new = NA)
for(i in 1:nrow(rand_string2)){
#print(paste0("rand_string2$animal[i]:",rand_string2$animal[i]))
for(j in 1:nrow(animal)){
if(grepl(animal$animal[j],rand_string2$animal[i])){
#print(animal$animal[j])
rand_string2$new[i] = animal$type[j]
}
}
}
View(rand_string2)

我尝试了一些应用函数,但由于它们有不同的行数,所以出现了错误。任何帮助都将不胜感激!

更新:我更新了动物数据帧的代码示例,以反映原始数据帧

更新数据:

animal <- data.frame(animal = c("llama|deer|hound|meerkat|coyote", "hawk|parrot|finch", "bee|junebug|butterfly"),
type = c("mamal", "bird", "insect"))

再次更新:fuzzyjoin::regex_left_join((适用于实际数据帧中的无模式列。它需要一些时间,但没有循环那么多。感谢@benson23

在这种情况下,您不需要使用for loopapplyleft_join()已经足够了。

您可以使用fuzzy join::regex_left_join()dplyr::left_join()。但是,由于rand_string数据帧中有100万行,regex_left_join()可能效率太低。因此,我建议使用dplyr::left_join()

首先将";形容词";在您的rand_string中,以便可以使用纯动物名称来加入animal数据集。然后将animal数据帧中的多个记录拆分为每行一个记录。之后,left_join将两个集合移除,并移除新创建的animal2列,以及从typenewrename

代码

library(dplyr)
rand_string$animal2 <- gsub("^[a-z].+?(?<=_)", "", rand_string$animal, perl = T)
left_join(rand_string, 
separate_rows(animal, animal, sep = "\|"), 
by = c("animal2" = "animal")) |> 
select(-animal2) |> 
rename("new" = "type")

数据

set.seed(52)
animal <- data.frame(animal = c("llama|deer|hound|meerkat|coyote", "hawk|parrot|finch", "bee|junebug|butterfly"),
type = c("mamal", "bird", "insect"))
rand_string <- ids::adjective_animal(1E6, n_adjectives=1) %>% as.data.frame() %>% rename(animal = ".")

最新更新