R中的自连接

R中的自连接,r,dataframe,join,dplyr,tibble,R,Dataframe,Join,Dplyr,Tibble,下面是一个tibble示例: test <- tibble(a = c("dd1","dd2","dd3","dd4","dd5"), name = c("a", "b", "c", "d", "e"), b = c("dd3","dd4","dd1","dd5","dd2")) 我的表太大了(2.7M行4列),出现以下错误: 错误:std::错误\u alloc 请告知如何正确操作/最佳实践 我的最终目标是获得以下结构:

下面是一个tibble示例:

test <- tibble(a = c("dd1","dd2","dd3","dd4","dd5"), 
               name = c("a", "b", "c", "d", "e"), 
               b = c("dd3","dd4","dd1","dd5","dd2"))
我的表太大了(2.7M行4列),出现以下错误:

错误:std::错误\u alloc

请告知如何正确操作/最佳实践

我的最终目标是获得以下结构:

   a     name  b     b_name
   dd1   a     dd3   c
   dd2   b     dd4   d
   dd3   c     dd1   a
   dd4   d     dd5   e
   dd5   e     dd2   b 

对于这样的行数,我认为
data.table
可能会给您带来更快的速度。下面是data.table解决方案:

library(data.table)
setDT(test)
方法1:自连接: 方法2:使用数据。表::合并:
下面是另一个使用
base
中的
match
函数和
dplyr
包中的
mutate
的简单解决方案:

library(dplyr)

new_test <- test %>% 
  mutate(b_name = name[match(test$b,test$a)])
库(dplyr)
新测试%
变异(b_name=name[匹配(测试$b,测试$a)])

但是,要小心使用很长的表,因为
match
可能不是最佳的实现。

另一个选项是
fmatch
from
fastmatch

library(fastmatch)
test$b_name <- with(test, name[fmatch(b, a)])
test$b_name
#[1] "c" "d" "a" "e" "b"
库(快速匹配)

测试$b_name我没有收到此错误。但是我收到了一个关于
a
列的额外列。@yarnabrina对不起,我刚刚编辑了这个问题,这个问题对你的长表有效吗?:
new\u test%mutate(b\u name=name[match(test$b,test$a)])
@VitaliAvagyan工作得很好,检查是否符合要求。请添加作为答案并解释。不起作用…>vecseq(f_uuu,len_uuu,if(allow.cartesian | | notjoin | | | |!anyDuplicated(f_uuu,):连接结果超过2^31行(内部vecseq达到物理限制)。很可能是指定错误的联接。请检查i中是否存在重复的键值,其中每个键值都会一次又一次地联接到x中的同一组。如果没有问题,请尝试by=.EACHI为每个组运行j以避免较大的分配。否则,请在常见问题解答、Wiki、堆栈溢出和data.table问题跟踪器中搜索此错误消息以获取建议。“检查i中是否存在重复的键值,每个键值都会反复加入x中的同一组。"这并不是说它不起作用,而是因为你有很多重复的值,这导致了一个巨大的data.frame。如果你真的需要那堆重复的值,你可以尝试
by=.EACHI
,但当然,由于物理大小的限制,这可能不起作用。删除重复的值可能/合理吗?Vitaly showed是一个非常简单的匹配解决方案,它是有效的。它应该是一个简单的连接,但由于某些原因它不起作用。你怎么看?a和b之间的交集是3499,共有3500个可能的唯一id。请再次查看df,我有一个id和b id,它们来自同一组可能的id。其中一个被命名,我需要为其他id添加名称这是一个等级关系。你能告诉我怎么解决吗?@pavodive
merge(test, test, by.x = "a", by.y = "b")
library(dplyr)

new_test <- test %>% 
  mutate(b_name = name[match(test$b,test$a)])
library(fastmatch)
test$b_name <- with(test, name[fmatch(b, a)])
test$b_name
#[1] "c" "d" "a" "e" "b"