微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

评估下一个生日的人是谁

如何解决评估下一个生日的人是谁

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

  • 所有日期均采用每日格式 (%dD_m_Y),例如1926 年 1 月 18 日
  • 变量 date,它是所有其他日期应与之比较的参考日期
  • 变量 birth1,birth2,birth3,birth4,birth5,birth6 包含所有可能的家庭成员的生日。

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

示例数据:

日期 出生1 birth2 birth3 birth4 诞生5 诞生6
02feb2021 15jan1974 27nov1985
30nov2020 31aug1945 27jun1999 07apr1997
19nov2020 27sep1993 30dec1996
29jan2021 29mar1973
05dec2020 21jan1976 02oct1976 21jan1976 25may1995 1997 年 2 月 15 日
25nov2020 25nov1943 29nov1946
02feb2021 28apr1979

解决方法

已编辑为 2 月 29 日的帐户

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

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

制作示例数据

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

forvalue i = 1/6 {
    gen birth`i' = floor((mdy(12,1996)-mdy(12,1980)+1)*runiform() + mdy(12,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,year(date)) if month(birth) == 2 ///
& day(birth) == 29 & mod(year(date),4)!=0
replace person_next_birthday = mdy( month(birth),year(date) + 1) if person_next_birthday < date 
replace person_next_birthday = mdy(3,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)

最后一个循环是不必要的,但说明这对绑定是健壮的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。