首页 > 解决方案 > 评估谁是下一个生日的人

问题描述

在Stata中,我试图评估与给定日期相比,下一个给定生日是哪一个。我的数据如下所示:

例如:一个家庭有两个成年人 A 和 B。A 的生日是 1977 年 11 月 20 日,B 的生日是 1978 年 3 月 30 日。参考日期是 2020 年 11 月 29 日。我想知道下一个生日的人是谁,在上面的例子中是人B,因为人A在参考日期前一周过生日,所以这个家庭的下一个生日将在30 2021 年 3 月。

示例数据:

日期 出生1 出生2 出生3 出生4 出生5 出生6
2021 年 2 月 2 日 1974 年 1 月 15 日 27nov1985
2020 年 11 月 30 日 1945 年 8 月 31 日 1999 年 6 月 27 日 1997 年 4 月 7 日
2020 年 11 月 19 日 1993 年 9 月 27 日 1996 年 12 月 30 日
2021 年 1 月 29 日 1973 年 3 月 29 日
2020 年 12 月 5 日 1976 年 1 月 21 日 02oct1976 1976 年 1 月 21 日 1995 年 5 月 25 日 1997 年 2 月 15 日
2020 年 11 月 25 日 25nov1943 29nov1946
2021 年 2 月 2 日 1979 年 4 月 28 日

标签: datestata

解决方案


编辑至 2 月 29 日

*在 2 月 29 日不是闰年的情况下,编辑会将 2 月 29 日生日的人视为 3 月 1日。date如果这对您的特定用例没有意义,则应该很容易根据您认为合适的方式更改下面的代码。

由于您想要一年中的下一个生日而不是最近的生日,因此您可以使用年份date和月份和birth{i}日期为每个人的下一个生日创建日期。然后,您可以简单地从每个家庭中获取最早的值。我重塑了很久,并产生了一个人和一个家庭id来做到这一点。

制作示例数据

clear
set obs 6
set seed 1996
generate date = floor((mdy(12,31,2020)-mdy(12,1,2015)+1)*runiform() + mdy(12,1,2015))
format date %td

forvalue i = 1/6 {
    gen birth`i' = floor((mdy(12,31,1996)-mdy(12,1,1980)+1)*runiform() + mdy(12,1,1980)) if _n < `i' == 0
    format birth`i'  %td
}

replace birth6 = birth4 in 6 // want a tie
replace birth2 = date("29feb1996","DMY") in 3 // Feb 29

查找下一个生日

gen household_id = _n
reshape long birth, i(date household_id) j(person)
drop if mi(birth)

gen person_next_birthday = mdy( month(birth), day(birth), year(date))
* TREAT FEB 29 as if they have a march 1 birthday in non-leap years
replace person_next_birthday = mdy(3,1,year(date)) if month(birth) == 2 ///
& day(birth) == 29 & mod(year(date),4)!=0
replace person_next_birthday = mdy( month(birth), day(birth), year(date) + 1) if person_next_birthday < date 
replace person_next_birthday = mdy(3,1,year(date)+1) if month(birth) == 2 ///
& day(birth) == 29 & mod(year(date) + 1,4)!=0 & person_next_birthday < date
format person_next_birthday  %td

bysort household_id  (person_next_birthday): gen next_bday = person_next_birthday[1]
format next_bday %td
drop person_next_birthday

reshape wide birth, i(date household_id next_bday) j(person)

gen next_bday_persons = ""
* Make a string to present household persons who have next bday
foreach v of varlist birth* {
    local person = subinstr("`v'","birth","",.)
    local condition = "month(`v') == month(next_bday) & day(`v') == day(next_bday)"
    local condition_feb29 = "month(next_bday) == 3 & day(next_bday) == 1 & month(`v') == 2 & day(`v') == 29"
    replace next_bday_persons = next_bday_persons + "|`person'" if `condition' | `condition_feb29'
}
replace next_bday_persons = regexr(next_bday_persons,"^\|","")
order next_bday_persons, after(next_bday)

最后一个循环是不必要的,但说明这对关系是稳健的。


推荐阅读