date - 评估谁是下一个生日的人
问题描述
在Stata中,我试图评估与给定日期相比,下一个给定生日是哪一个。我的数据如下所示:
- 所有日期均采用每日格式 (%dD_m_Y),例如 18mar1926
- 变量
date
,它是所有其他日期应与之比较的参考日期 - 变量
birth1, birth2, birth3, birth4, birth5, birth6
包含所有可能的家庭成员的生日。
例如:一个家庭有两个成年人 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 日 |
解决方案
编辑至 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)
最后一个循环是不必要的,但说明这对关系是稳健的。
推荐阅读
- javascript - 我无法从 API 中获取不同的值,除了“鸡”
- c# - 循环调用 Rest API
- javascript - 停止在文本字段中输入(标签输入)
- pandas - 大熊猫中的 data[:,0] 或 data[:,1] 是什么意思
- c# - 从 istio Service Mesh 上的工作节点中的服务连接到 Kubernetes API Server
- macos - 使用 AppleScript 自动进行 FaceTime 音频通话
- laravel - 获取在laravel中找不到的路线
- javascript - 如果条件为真,如何在特定索引中的数组中插入数据,如果条件为假,如何插入零
- lua - 使用 luarocks 安装 lua 请求时出错
- android - Xamarin Forms如何从android中删除调试版本