使用dplyr按条件拆分tibble列,不符合条件填NA保持长度一致
解决方案
先还原你的原始数据:
library(tibble) library(dplyr) df <- tibble( A = c(1, 2, -3), B = c(0, 1, -2), C = c(-1, 2, 1) )
你之前用summarise()出错是因为这个函数是做聚合汇总的,输出行数会压缩,而你需要的是逐行生成新列、保持原数据行数,所以得用mutate()配合条件判断函数来实现。
根据你给出的期望输出,反推对应的条件,示例代码如下:
df_new <- df %>% mutate( # 当A < 0时保留A,否则填NA → 对应A_to_B列 A_to_B = ifelse(A < 0, A, NA), # 当B >= 0时保留A的值,否则填NA → 对应B_to_A列 B_to_A = ifelse(B >= 0, A, NA), # 当B < 0时保留B的值,否则填NA → 对应B_to_C列 B_to_C = ifelse(B < 0, B, NA) ) # 查看结果 df_new
运行后得到的结果和你期望的完全一致:
# A tibble: 3 × 6 A B C A_to_B B_to_A B_to_C <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 1 1 0 -1 NA 1 NA 2 2 1 2 NA 2 NA 3 -3 -2 1 -3 NA -2
核心要点
- 放弃
summarise():它的作用是聚合(比如求和、取均值),会把多行数据压缩成一行或分组后的行数,这就是你之前遇到“长度不一致”的根源。 - 用
mutate()生成新列:这个函数会为原数据的每一行生成对应新列的值,完全保留原数据的行数。 - 条件判断工具:
- 简单条件用
ifelse()足够,格式为ifelse(判断条件, 满足条件的取值, 不满足时填NA) - 多条件场景推荐用
case_when(),语法更直观,比如:mutate( new_col = case_when( A > 2 ~ A, B < 0 ~ B, TRUE ~ NA_real_ # 其他所有情况填NA ) )
- 简单条件用
批量处理扩展
如果要给大量列按相同规则生成新变量,用across()批量操作更高效,比如给每列生成“小于0时保留原值,否则填NA”的新列:
df %>% mutate( across(everything(), ~ifelse(.x < 0, .x, NA), .names = "{col}_neg") )
会自动生成A_neg、B_neg、C_neg列,完美适配多列场景。
内容的提问来源于stack exchange,提问作者Herr Student
相关产品推荐
相关产品推荐

