我有一个大的数据帧和另一个相对较小的不同行数的数据帧,我需要匹配任何项。我想使用应用族函数来避免嵌套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 loop
或apply
,left_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
列,以及从type
到new
的rename
。
代码
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 = ".")