R 连接数据帧而不创建重复行,同时在一列下连接唯一项

R 连接数据帧而不创建重复行,同时在一列下连接唯一项,r,dataframe,join,R,Dataframe,Join,我试图通过名为patient的特定变量将两个相互关联的数据帧合并在一起。第二个数据帧具有同一患者列的多个条目。我不希望在合并时创建重复的患者条目,但我希望通过将一列下的值串联在一起,在第二个数据帧中保留唯一的信息 我尝试使用group\u by手动连接某些变量,效果很好。但是,我有几个变量,手动指定所有变量是不可行的 我还可以使用dplyr连接数据帧中的每个变量,如下所示。第二种情况下的问题是,重复的值也被连接在一起,使得数据帧变得不必要的大,难以处理。请参阅下面的reprex 库(dplyr)

我试图通过名为
patient
的特定变量将两个相互关联的数据帧合并在一起。第二个数据帧具有同一患者列的多个条目。我不希望在合并时创建重复的患者条目,但我希望通过将一列下的值串联在一起,在第二个数据帧中保留唯一的信息

我尝试使用
group\u by
手动连接某些变量,效果很好。但是,我有几个变量,手动指定所有变量是不可行的

我还可以使用
dplyr
连接数据帧中的每个变量,如下所示。第二种情况下的问题是,重复的值也被连接在一起,使得数据帧变得不必要的大,难以处理。请参阅下面的reprex

库(dplyr)
#> 
#>正在附加包:“dplyr”
#>以下对象已从“package:stats”屏蔽:
#> 
#>滤波器,滞后
#>以下对象已从“package:base”屏蔽:
#> 
#>相交、setdiff、setequal、并集
df1患者var1 var2
#>1111
#>2B212
#>3 c 3 13
df2患者治疗时间var3
#>1 a药物1时间1常数
#>2 a药物2时间2常数
#>3 b药物1时间1常数
#>4 b药物2时间2常数
#>5 c 1时间1常数
#>6 c 2时间2常数
df_合并加入,由=“患者”
#我不想要像这样的复制品
df_合并
#>患者var1 var2治疗时间var3
#>1 a 11药物1时间1常数
#>2 a 11药物2时间常数
#>3 b 2 12药物1时间常数
#>4 b 2 12药物2时间2常数
#>5 c 3 13药物1时间常数
#>6 c 3 13药物2时间常数
df_合并2%
分组依据(患者)%>%
突变(治疗=粘贴(治疗,塌陷=“”),
时间=粘贴(时间,折叠“”)%>%
过滤器(!重复(患者))
#我可以像这样手动编辑一些变量
df_合并2
#>#tibble:3 x 6
#>#分组:患者[3]
#>患者var1 var2治疗时间var3
#>                         
#>1 a 11药物1_药物2时间1_时间2常数
#>2B212药物1\u药物2时间1\u时间2常数
#>3 c 3 13药物1_药物2时间1_时间2常数
df_合并3%
分组依据(患者)%>%
mutate_at(vars(-group_cols()),.funs=~粘贴(,collapse=“”))%>%
过滤器(!重复(患者))
#我有许多无法手动指定的变量
#我可以创建这个合并的数据帧,但我不想
#连接重复的值,如var1、var2和var3
df_合并3
#>#tibble:3 x 6
#>#分组:患者[3]
#>患者var1 var2治疗时间var3
#>                                  
#>1一个1_11_11药物1_药物2时间1_时间2常数
#>2 b 2_2 12_12药物1_药物2时间1_时间2常数
#>3 c 3_3 13_13药物1_药物2时间1_时间2常数
由(v0.3.0)于2019-10-23创建

我想看看是否有一种方法可以连接只包含唯一值的变量,以保留第二个数据帧中的信息,而不复制
df\u merged
中的行

我很高兴听到您除了
dplyr
之外还有什么建议。
data.table
解决方案也可能适合我,因为我的实际数据帧非常大


谢谢

我们可以使用
唯一

library(dplyr)
df_merged %>%
          group_by(patient) %>%
          summarise_at(vars(-group_cols()), .funs = ~paste(unique(.), collapse ="_"))
或者我们可以直接进行合并/联合,而不是使用中间数据帧添加/更改全局环境

left_join(df1, 
          df2 %>% group_by(patient) %>% 
                  summarise_at(vars(-group_cols()), .funs = ~paste(unique(.), collapse ="_")) %>% 
                  ungroup()
         )

Joining, by = "patient"
  patient var1 var2   treatment        time     var3
1       a    1   11 drug1_drug2 time1_time2 constant
2       b    2   12 drug1_drug2 time1_time2 constant
3       c    3   13 drug1_drug2 time1_time2 constant
更新
有道理。谢谢请写下这个作为答案,这样我就可以给你投票了。当重复行中有
NA
s时,有没有办法添加一个符号来保留有关缺失的信息?因此,如果将4个数据点(例如,
“drug1,NA,NA,drug2”
)连接在一起,我仍然可以作为
drug1.\uu.\uDrug2
跟踪条目。我想保留订单谢谢。但是,在
Reduce
函数的上下文中,我无法将注意力集中在
v
u
之间的关系上。你能详细说明一下吗?还有一点很有帮助:我最初的目标是避免粘贴重复值(所有重复值都相同)。但是,如果有这样一种情况,比如说,患者按照这种特定顺序接受
“drug1,NA,NA,drug2,NA,drug1,drug2”
治疗,我希望能够在串联输出中看到这一点,即
“drug1.\uu drug2.\u drug1.\u drug2”
。这可能吗?我想我在谷歌的帮助下发现了一些东西。这可以做我想要的非重复副本,但它也粘贴了完全重复的副本:模拟数据
df2我的意思是我想将
“drug1,NA,NA,drug2,drug1,drug2”转换为
“drug1.\uu drug2.\u drug1\u drug2”
,但我想防止
“drug1,drug1,drug1”
变成
“drug1\u drug1\u drug1”
。非常感谢您的帮助,我非常感谢!
#Here a toy example to experiment with, uncomment browser to see how it works inside Reduce, 
#also see ?Reduce for more info 
paste_mod <- function(x) Reduce(function(u, v){
u <- ifelse(!grepl('_',u) & is.na(u),'.',u)
v <- ifelse(is.na(v),'.',v)
if(v=='.' | !grepl(v,u)) paste0(u,'_',v) else u
}, x)

paste_mod(c("drug1",NA,NA,"drug2","drug1","drug2"))
[1] "drug1_._._drug2"
paste_mod(c(NA,NA,"drug2","drug1","drug2"))
[1] "._._drug2_drug1"

#replace NA with . then apply Reduce
df2 %>% 
       mutate_if(is.factor,as.character) %>% mutate_all(~replace(.,is.na(.),'.')) %>% 
       group_by(patient) %>% 
       summarise_at(vars(-group_cols()), .funs = ~Reduce(function(u, v) if(v=='.' | !grepl(v,u)) paste0(u,'_',v) else u, .)) %>% 
       ungroup()

# A tibble: 2 x 4
  patient treatment       time        var3    
  <chr>   <chr>           <chr>       <chr>   
1 a       drug1_._._drug2 time1_time2 constant
2 c       drug1_drug2     time1_time2 constant
df2 <- structure(list(patient = structure(c(1L, 1L, 1L, 1L, 2L, 2L), .Label = c("a", 
"c"), class = "factor"), treatment = structure(c(1L, NA, NA, 
2L, 1L, 2L), .Label = c("drug1", "drug2"), class = "factor"), 
    time = structure(c(1L, 2L, 1L, 2L, 1L, 2L), .Label = c("time1", 
    "time2"), class = "factor"), var3 = structure(c(1L, 1L, 1L, 
    1L, 1L, 1L), class = "factor", .Label = "constant")), class = "data.frame", row.names = c(NA, 
-6L))