Date 评估谁是下一个生日的人

Date 评估谁是下一个生日的人,date,stata,Date,Stata,在斯塔塔,我试图评估与给定日期相比,哪个给定的生日是下一个生日。我的数据如下所示: 所有日期均为每日格式(%dD\u m\Y),例如1926年3月18日 变量date是所有其他日期都应与之进行比较的参考日期 变量birth1、birth2、birth3、birth4、birth5、birth6包含所有可能家庭成员的生日 例如:一个有两个成年人A和B的家庭。A的生日是1977年11月20日,B的生日是1978年3月30日。参考日期为2020年11月29日。我想知道谁是下一个生日的人,在上面的例

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

  • 所有日期均为每日格式(%dD\u m\Y),例如1926年3月18日
  • 变量
    date
    是所有其他日期都应与之进行比较的参考日期
  • 变量
    birth1、birth2、birth3、birth4、birth5、birth6
    包含所有可能家庭成员的生日
例如:一个有两个成年人A和B的家庭。A的生日是1977年11月20日,B的生日是1978年3月30日。参考日期为2020年11月29日。我想知道谁是下一个生日的人,在上面的例子中是B,因为A的生日在参考日期前一周,所以这个家庭的下一个生日将在2021年3月30日庆祝

示例数据:

日期 出生1 出生2 出生3 出生4 出生的 出生的 2002年2月2日 1974年1月15日 1985年11月27日 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日 1976年10月2日 1976年1月21日 1995年5月25日 1997年2月15日 2020年11月25日 1943年11月25日 1946年11月29日 2002年2月2日 1979年4月28日
编辑以说明2月29日的情况

*该编辑将把2月29日生日的人视为3月1日,因为
date
的年份不是闰年。如果这对您的特定用例没有意义,那么根据您的需要修改下面的代码应该很容易

由于您希望一年中的下一个生日而不是最近的生日,因此可以使用
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,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
清除
设置obs 6
1996年播种
生成日期=下限((mdy(12,312020)-mdy(12,12015)+1)*runiform()+mdy(12,12015))
格式日期%td
forvalue i=1/6{
gen Borth`i'=地板((mdy(12,311996)-mdy(12,11980)+1)*符形()+mdy(12,11980))如果_n<`i'==0
格式化“i”%td
}
替换birth6=6中的birth4//想要领带吗
将birth2=日期(“1996年2月29日”,“DMY”)替换为2月29日的3//
查找下一个生日

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)
gen household\u id=\n
重塑长出生,i(日期家庭id)j(人)
如果mi(出生)下降
gen person\u next\u birth=mdy(月(出生)、日(出生)、年(日期))
*将2月29日视为非闰年的3月1日生日
如果月份(出生)=2,则更换下一个生日=mdy(3,1,年(日期))的人员///
&日期(出生)==29和日期(年份(日期),4)=0
如果人员下一个生日<日期,则替换人员下一个生日=mdy(月(出生)、日(出生)、年(日期)+1
如果月份(出生)=2,则替换人员下一个生日=mdy(3,1,年(日期)+1)///
&天(出生)==29和月(年(日期)+1,4)=0人下一个生日<日期(&U)
设置人员下一个生日的格式%td
bysort House_id(下一个生日的人):gen next_bday=下一个生日的人[1]
格式化下一天%td
在下一个生日送人
重塑宽幅出生,i(日期家庭身份证下一天)j(人)
gen next_bday_persons=“”
*制作一个字符串来表示有下一个B日的家庭成员
varlist出生的foreach v*{
当地人=副词(“'v',”出生“,”,)
局部条件=“月(`v')==月(下一天)&day(`v')==天(下一天)”
当地情况29=“月(下一天)=3天(下一天)=1个月(`v')==2天(`v')==29”
如果“条件”|“条件”|“2月29日”
}
替换next_bday_persons=regexr(next_bday_persons,“^\”和“)
订购下一天的人,在(下一天)之后

最后一个循环是不必要的,但它说明了这对领带很有效。

编辑为2月29日的原因

*该编辑将把2月29日生日的人视为3月1日,因为
date
的年份不是闰年。如果这对您的特定用例没有意义,那么根据您的需要修改下面的代码应该很容易

由于您希望一年中的下一个生日而不是最近的生日,因此可以使用
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,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
清除
设置obs 6
1996年播种
生成日期=下限((mdy(12,312020)-mdy(12,12015)+1)*runiform()+mdy(12,12015))
格式日期%td
forvalue i=1/6{
gen Borth`i'=地板((mdy(12,311996)-mdy(12,11980)+1)*符形()+mdy(12,11980))如果_n<`i'==0
格式化“i”%td
}
替换birth6=6中的birth4//想要领带吗
将birth2=日期(“1996年2月29日”,“DMY”)替换为2月29日的3//
查找下一个生日

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)
gen household\u id=\n
重塑长出生,i(日期家庭id)j(人)
如果mi(出生)下降
gen person\u next\u birth=mdy(月(出生)、日(出生)、年(日期))
*将2月29日视为非闰年的3月1日生日
如果月份(出生)=2,则更换下一个生日=mdy(3,1,年(日期))的人员///
&日期(出生)==29和日期(年份(日期),4)=0
如果人员下一个生日<日期,则替换人员下一个生日=mdy(月(出生)、日(出生)、年(日期)+1
如果月份(出生)=2,则替换人员下一个生日=mdy(3,1,年(日期)+1)///
&天(出生)==29和月(年(日期)+1,4)=0人下一个生日<日期(&U)
设置人员下一个生日的格式%td
bysort House_id(下一个生日的人):gen next_bday=下一个生日的人[1]
格式化下一天%td
在下一个生日送人
重塑宽幅出生,i(日期家庭身份证下一天)j(人)
gen next_bday_persons=“”
*制作一个字符串以进行预处理