我有两个 Dataframe ,如下所示:
df1 <- data.frame(Marker1=c('+','+','+','-','-'), Marker2=c('+','+','+','+','-'), Marker3=c('+','-','+','-','+'),
Sample=c(1,1,2,3,3), Population_ID=c(1,2,1,5,6), Cells_in_Sample=c(443,23,567,98,3))
df2 <- data.frame(Population_ID=c(1,1,1,1,1,1,1,2,2,2,2,2,2,2,5,5,5,5,5,5,5,6,6,6,6,6,6,6),
Marker1=c('+','+','+','+',NA,NA,NA,'+','+','+','+',NA,NA,NA,'-','-','-','-',NA,NA,NA,'-','-','-','-',NA,NA,NA),
Marker2=c('+','+',NA,NA,'+','+',NA,'+','+',NA,NA,'+','+',NA,'+','+',NA,NA,'+','+',NA,'-','-',NA,NA,'-','-',NA),
Marker3=c('+',NA,'+',NA,'+',NA,'+','-',NA,'-',NA,'-',NA,'-','-',NA,'-',NA,'-',NA,'-','+',NA,'+',NA,'+',NA,'+'))
它们看起来像这样:
> df1
Marker1 Marker2 Marker3 Sample Population_ID Cells_in_Sample
1 + + + 1 1 443
2 + + - 1 2 23
3 + + + 2 1 567
4 - + - 3 5 98
5 - - + 3 6 3
> head(df2)
Population_ID Marker1 Marker2 Marker3
1 1 + + +
2 1 + + <NA>
3 1 + <NA> +
4 1 + <NA> <NA>
5 1 <NA> + +
6 1 <NA> + <NA>
df1
包含我的“基础”群体,具有3个标记的组合(所有3个都存在),加上每个样本的每个群体的计数(Cells_in_Sample
)。df2
采用3个标记的唯一组合,并从中产生1和2的所有可能组合。请注意,df2
已经包含了来自df1
的“基本”种群。
我在这里要做的就是生成一个final_df
,以一种高效而优雅的方式将两者结合起来,尽可能避免嵌套循环。final_df
应保留df1
中每个“基础”3标记组合的样本和计数值,并扩展到df2
中的所有“子组合”。因此,我应该用Sample
和Population_ID
来rbind
它们。
现在我设法做到了这一点,使用嵌套的for
循环,但我想知道是否有更好的解决方案。
这就是我所做的:
final_df <- NULL
for (s in unique(df1$Sample)){
df1_sub <- subset(df1, Sample==s)
for (p in df1_sub$Population_ID){
df1_sub_sub <- subset(df1_sub, Population_ID==p)
df2_sub <- subset(df2, Population_ID==p)
df2_sub$Sample <- s
df2_sub$Cells_in_Sample <- df1_sub_sub$Cells_in_Sample
df2_sub <- df2_sub[,c(2,3,4,5,1,6)]
#note there is no need to rbind df1_sub_sub and df2_sub
#cause df2 already contains the populations from df1
final_df <- rbind(final_df, df2_sub)
}
}
final_df
看起来就像我想要的。我把它贴在下面以供参考:
> final_df
Marker1 Marker2 Marker3 Sample Population_ID Cells_in_Sample
1 + + + 1 1 443
2 + + <NA> 1 1 443
3 + <NA> + 1 1 443
4 + <NA> <NA> 1 1 443
5 <NA> + + 1 1 443
6 <NA> + <NA> 1 1 443
7 <NA> <NA> + 1 1 443
8 + + - 1 2 23
9 + + <NA> 1 2 23
10 + <NA> - 1 2 23
11 + <NA> <NA> 1 2 23
12 <NA> + - 1 2 23
13 <NA> + <NA> 1 2 23
14 <NA> <NA> - 1 2 23
15 + + + 2 1 567
16 + + <NA> 2 1 567
17 + <NA> + 2 1 567
18 + <NA> <NA> 2 1 567
19 <NA> + + 2 1 567
20 <NA> + <NA> 2 1 567
21 <NA> <NA> + 2 1 567
151 - + - 3 5 98
161 - + <NA> 3 5 98
171 - <NA> - 3 5 98
181 - <NA> <NA> 3 5 98
191 <NA> + - 3 5 98
201 <NA> + <NA> 3 5 98
211 <NA> <NA> - 3 5 98
22 - - + 3 6 3
23 - - <NA> 3 6 3
24 - <NA> + 3 6 3
25 - <NA> <NA> 3 6 3
26 <NA> - + 3 6 3
27 <NA> - <NA> 3 6 3
28 <NA> <NA> + 3 6 3
有没有一种简单有效的方法来做到这一点,而不需要嵌套循环?我的实际数据比这个大很多倍。
谢谢你,谢谢
2条答案
按热度按时间np8igboo1#
你根本不需要循环,这是一个
merge
的例子。在下面的代码中,我复制了一个
final_df
,只是为了测试,以保持预期的结果。创建于2023-09-29带有reprex v2.0.2
kkbh8khc2#
您想要的结果可以通过
left_join()
来实现。1.删除
df1
中的Marker列,因为这些列已经包含在df2
中。left_join()
两个数据集。1.重新排列列和行以匹配问题中的结果表。