dplyr管道下使用bind_rows做列对行绑定如何避免重复值与NA值
管道流中
bind_rows实现无NA、无冗余行绑定的操作指南 代码失效的根因
管道操作符%>%的默认规则是把左侧的对象作为函数的第一个位置参数传入。你之前编写的代码:
df %>% bind_rows( select(., 1:2), select(., 3:4) )
实际等价于执行下面的逻辑:
bind_rows( df, # 管道自动把原df作为第一个绑定项 select(df, 1:2), select(df, 3:4) )
总共绑定了3个数据框,因为后两个子集和原df的列名不匹配,所以才会出现9行、带NA、夹杂原表重复内容的结果,和bind_rows本身的核心功能无关。
管道流中的正确实现方式
要实现「col1-col2列对、col3-col4列对按行绑定,最终2列6行、无NA无冗余」的效果,两种符合tidyverse逻辑的写法都可直接使用:
写法1:对齐参考实现逻辑,先统一列名再绑定
df %>% # 先给4列设置重复的统一列名,让两个子集的列名完全一致 set_names(rep(c("newcol1", "newcol2"), 2)) %>% bind_rows( select(., 1:2), select(., 3:4) )
运行后会直接得到预期的6行2列输出,没有NA、没有原表的重复内容。
写法2:截断管道自动传值,避免原表被意外拼入
如果不想提前对全表重命名,可以用{}截断管道的自动传值规则,不让原表成为bind_rows的第一个参数,手动对齐两个子集的列名即可:
df %>% { # 手动指定两个待绑定的子集,原表不会被自动加入绑定列表 bind_rows( select(., 1:2) %>% set_names(c("newcol1", "newcol2")), select(., 3:4) %>% set_names(c("newcol1", "newcol2")) ) }
关于bind_rows内部嵌套子集选择函数的说明
完全可以在bind_rows的入参域内嵌套使用select、filter等子集操作函数,这和Hadley Wickham提到的在bind_rows内嵌套filter的写法逻辑完全一致——本质是利用. 指代管道传入的源数据框,在函数参数域内自由做数据变换。
实际使用中只要注意两个核心规则就能避免踩坑:
- 要清楚管道自动传值的行为:如果不需要把源数据框本身拼入绑定列表,记得用
{}截断自动传值,或者明确列全所有待绑定的子集,不要让原表被默认当第一个绑定项。 - 要对齐所有待绑定子集的列名:
bind_rows的设计逻辑是按列名对齐,列名不一致就会自动补NA,要得到无NA的绑定结果,必须保证所有待绑定子集的列名完全相同。
内容的提问来源于stack exchange,提问作者Anoushiravan R
相关产品推荐
相关产品推荐

