You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

纵向数据按id和gen分组计算time2-time1的缺失时间点处理咨询

问题描述

我有一份纵向数据库,变量说明:

  • id:个体标识
  • grup_int:分组分类变量
  • gen:待测量变量
  • time:测量时间点
  • value:测量值

数据示例:

id grup_int gen   time   value
     <dbl>    <dbl> <chr> <chr>  <dbl>
1 60801001        1 adrb2 2     2.11  
2 60801001        1 ccl2  1     0.941 
3 60801001        1 ccl2  2     0.248 
4 60801001        1 ccl3  1     5.65  
5 60801001        1 ccl3  2     NA

尝试用以下代码计算time=2与time=1的value差值:

df %>% dplyr::group_by(id, gen) %>%  dplyr::mutate(d_post_pre =  value [time == 2] - value [time == 1])

运行后报错:

`d_post_pre` must be size 1, not 0.
ℹ The error occurred in group 1: id = 60801001, gen = "adrb2".

报错原因是部分组(如adrb2)缺少time=1的条目;另外存在time点齐全但value为NA的情况(如ccl3),这种情况无需特殊处理,保留NA即可。需要修改代码规避报错,缺失必要时间点时返回NA或特定值方便后续过滤。

附数据结构:

df <- structure(list(id = structure(c(60801001, 60801001, 60801001, 
60801001, 60801001), label = "Identificador", format.spss = "F9.0", display_width = 14L), 
    grup_int = structure(c(1, 1, 1, 1, 1), format.spss = "F2.0"), 
    gen = c("adrb2", "ccl2", "ccl2", "ccl3", "ccl3"), time = c("2", 
    "1", "2", "1", "2"), value = c(2.1098254, 0.94088, 0.24778089, 
    5.6529145, 0.06939283)), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -5L))
解决方案

方法1:用first()提取对应时间点的value

通过first()提取指定time的value,当某个time不存在时会返回NA,差值计算自然得到NA,不会触发报错:

df %>%
  dplyr::group_by(id, gen) %>%
  dplyr::mutate(
    d_post_pre = first(value[time == "2"]) - first(value[time == "1"])
  ) %>%
  dplyr::ungroup()

方法2:转宽格式计算差值(更直观)

先将长格式数据转为宽格式,让time=1和time=2的value各占一列,计算差值后可按需转回长格式:

# 转宽格式并计算差值
df_wide <- df %>%
  dplyr::pivot_wider(
    id_cols = c(id, grup_int, gen),
    names_from = time,
    values_from = value,
    names_prefix = "time_"
  ) %>%
  dplyr::mutate(d_post_pre = time_2 - time_1)

# 如需转回长格式
df_long <- df_wide %>%
  dplyr::pivot_longer(
    cols = starts_with("time_"),
    names_to = "time",
    values_to = "value",
    names_prefix = "time_"
  ) %>%
  dplyr::select(id, grup_int, gen, time, value, d_post_pre)

方法3:先汇总差值再关联回原数据

如果只需要每个(id, gen)组的差值,先汇总生成差值表,再左连接到原数据:

diff_df <- df %>%
  dplyr::group_by(id, gen) %>%
  dplyr::summarise(
    d_post_pre = first(value[time == "2"]) - first(value[time == "1"]),
    .groups = "drop"
  )

df %>%
  dplyr::left_join(diff_df, by = c("id", "gen"))

以上方法都会在缺少time=1或time=2时返回NA,value本身的NA会保留在差值结果中,符合需求。

内容的提问来源于stack exchange,提问作者Javier Hernando

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 23:43:24