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

如何用dplyr处理家庭面板数据,生成grandparent与became_grandparent变量?

祖父母身份标记与首次成为祖父母年份计算

问题背景

样本数据

id <- c(10020,10020,10020,10020,10020,10020,10020,10020,10021,10021,10021,10021,
        10021,10021,10022,10022,10022,20020,20020,20020,20020,20020,20020,20021,
        20021,20021)
family_id<- c(1002,1002,1002,1002,1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002,
             1002, 1002, 1002, 1002, 1002, 2002, 2002, 2002, 2002, 2002, 2002, 
             2002, 2002, 2002 )
child_id<- c(NA, NA, NA, NA, NA, NA, NA, NA, 1, 1, 1, 1, 1, 2, 2, 2, 2, NA, NA, 
            NA, NA, NA, NA, 1, 1, 1 )
year<- c(2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2002, 2003, 2004, 2005,
         2006, 2004, 2005, 2006, 2007, 2002, 2003, 2004, 2005, 2006, 2007, 2004,
         2005, 2006 ) 
number_of_children<- c(2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2,
                       2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0 )
child1_birthyear<- c(1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980, 2001, 2001,
                     2001, 2001, 2001, NA, NA, NA, NA, 1990, 1990, 1990, 1990, 
                     1990, 1990, NA, NA, NA )
child2_birthyear<- c(1984, 1984, 1984, 1984, 1984, 1984, 1984, 1984, 2004, 2004,
                     2004, 2004, 2004, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
                     NA, NA, NA )
sample<- data.frame(id,family_id,child_id,year,number_of_children,
                    child1_birthyear,child2_birthyear) 

数据规则

  • id最后一位为0代表父母数据,大于0代表子女数据;
  • 以家庭ID1002为例:10020是父母数据,10021、10022分别为1980年、1984年出生的子女;父母的子女10021在2006年有2个孩子(出生于2001年、2004年),10022无子女。

需求

生成两个变量:

  1. grandparent:标识变量,父母为祖父母时取值1,否则0;
  2. became_grandparent:父母成为祖父母的年份,即其子女首次生育的最早年份(孙辈最早出生年份)。

尝试的代码(未得到正确结果)

sample<-sample%>%
  arrange(year,id)%>%
  group_by(family_id)%>%
  mutate(
    became_grandparent=min(tail(child1_birthyear,-1),na.rm=TRUE)
  )%>%
  arrange(id,year)

解决方案

原代码未区分父母与子女行,且仅提取child1_birthyear的部分值,逻辑不符合需求。以下是基于dplyr的正确实现:

library(dplyr)

sample_processed <- sample %>%
  # 标记当前行是否为父母行(id最后一位为0)
  mutate(is_parent = substr(as.character(id), nchar(as.character(id)), nchar(as.character(id))) == "0") %>%
  group_by(family_id) %>%
  mutate(
    # 收集当前家庭所有子女行的孙辈出生年份(child1和child2)
    grandchild_births = list(c(
      child1_birthyear[!is_parent],
      child2_birthyear[!is_parent]
    )),
    # 计算首次成为祖父母的年份:取孙辈最早的出生年份,无孙辈则为NA
    became_grandparent = ifelse(length(na.omit(unlist(grandchild_births))) > 0,
                                min(na.omit(unlist(grandchild_births))),
                                NA),
    # 标记祖父母身份:父母行有孙辈则为1,无则为0;子女行设为NA
    grandparent = case_when(
      is_parent & !is.na(became_grandparent) ~ 1L,
      is_parent & is.na(became_grandparent) ~ 0L,
      TRUE ~ NA_integer_
    )
  ) %>%
  # 清理临时变量
  select(-is_parent, -grandchild_births) %>%
  ungroup() %>%
  # 按id和年份排序,还原原顺序
  arrange(id, year)

代码解释

  1. 标记父母行:通过提取id最后一位判断是否为父母数据;
  2. 收集孙辈出生年份:按家庭分组后,收集所有子女行的child1_birthyear和child2_birthyear,形成列表;
  3. 计算首次成为祖父母年份:如果有非NA的孙辈出生年份,取最小值作为首次成为祖父母的年份,无孙辈则设为NA;
  4. 标记祖父母身份:仅对父母行赋值,有孙辈则为1,无则为0;子女行设为NA;
  5. 清理与排序:移除临时变量,按id和年份排序还原原数据顺序。

验证结果

  • 家庭1002的父母行(id=10020):grandparent=1,became_grandparent=2001(对应孙辈最早出生年份);
  • 家庭2002的父母行(id=20020):grandparent=0,became_grandparent=NA(无孙辈);
  • 所有子女行的grandparent和became_grandparent均为NA,符合需求。

内容的提问来源于stack exchange,提问作者Ludwig Gershwin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 03:17:14