R语言:基于同一个体同一疾病多日期创建新列的if_else报错解决
问题:用dplyr的if_else实现分组条件生成新列
现有数据表格:
| ID | conception | date_Dx | Dx |
|---|---|---|---|
| 1 | 2005-11-14 | 2008-10-01 | xx |
| 1 | 2005-11-14 | 2008-04-08 | yy |
| 1 | 2005-11-14 | 2008-10-05 | xx |
| 1 | 2005-11-14 | 2008-04-08 | zz |
需求:创建新列copy_Dx,当同一ID+conception分组下的同一Dx对应多个不同date_Dx时,copy_Dx取Dx的值;否则取"0"。
尝试的dplyr代码:
df1 <- df%>% group_by(ID, conception, Dx)%>% mutate(copy_Dx = if_else(n_distinct(date_Dx)>1, Dx,"0"))%>% ungroup()
运行后报错:
Caused by error in
if_else():
!truemust have size 1, not size 2.
替换成base的ifelse后代码可正常运行,现需用if_else实现该需求。
解决方案
if_else和base::ifelse的核心区别在于严格的长度匹配要求:if_else要求条件、true分支、false分支的长度必须完全一致,而ifelse会自动循环短向量来匹配长度。
原代码中,n_distinct(date_Dx)>1是分组后的单个布尔值(长度1),而Dx是当前组的多行值(比如xx组有2行,Dx长度为2),"0"是长度1的字符串,三者长度不匹配导致报错。
要解决这个问题,只需让条件和分支的长度统一,有两种简洁的实现方式:
方式1:先生成组内统一的条件标记
先在分组内生成一个和组内行数一致的逻辑向量,再用if_else判断:
df1 <- df %>% group_by(ID, conception, Dx) %>% # 生成每组的重复逻辑标记,长度等于组内行数 mutate(has_multi_dates = n_distinct(date_Dx) > 1) %>% # 此时条件、Dx、"0"长度完全匹配 mutate(copy_Dx = if_else(has_multi_dates, Dx, "0")) %>% ungroup() %>% # 可选:删除中间标记列 select(-has_multi_dates)
方式2:直接构造等长的分支向量
手动让false分支的长度匹配当前组的行数:
df1 <- df %>% group_by(ID, conception, Dx) %>% mutate(copy_Dx = if_else( n_distinct(date_Dx) > 1, Dx, rep("0", n()) # 生成和组内行数一致的"0"向量 )) %>% ungroup()
两种方式都能得到正确结果:
| ID | conception | date_Dx | Dx | copy_Dx |
|---|---|---|---|---|
| 1 | 2005-11-14 | 2008-10-01 | xx | xx |
| 1 | 2005-11-14 | 2008-04-08 | yy | 0 |
| 1 | 2005-11-14 | 2008-10-05 | xx | xx |
| 1 | 2005-11-14 | 2008-04-08 | zz | 0 |
内容的提问来源于stack exchange,提问作者Uknowepi
相关产品推荐
相关产品推荐

