如何基于cyclelength与startmenstr生成月经周期日cycleday变量?
生成月经周期日(cycleday)变量的实现方案
核心计算逻辑
cycleday的本质是以月经开始日为起点(cycleday=1),按个体周期长度循环计数,需自动处理两种场景:
- 月经开始日之后的日期:依次递增至周期长度,随后回到1循环
- 月经开始日之前的日期:从周期长度倒推计数(如月经前1天为cyclelength,前2天为cyclelength-1)
核心公式(以每个研究对象ID为分组单位):
- 计算当前
studyday与月经开始日startmenstr的偏移量:offset = studyday - startmenstr - 用周期长度对偏移量取模,再加1得到标准计数的cycleday:
cycleday = (offset %% cyclelength) + 1
模运算会自动处理正负偏移:
- 正偏移(studyday在月经开始日后):余数范围为0cyclelength-1,加1后对应1cyclelength的顺次计数
- 负偏移(studyday在月经开始日前):负数的模运算返回正数余数(如R中
-1 %% 5 = 4),加1后刚好对应周期后半段的倒序计数
R语言实现(dplyr)
library(dplyr) # 构造示例数据 df <- tibble( ID = rep(1:2, each = 35), studyday = rep(1:35, 2), cyclelength = c(rep(5, 35), rep(7, 35)), startmenstr = c(rep(2, 35), rep(4, 35)) ) # 分组计算cycleday df <- df %>% group_by(ID) %>% mutate( offset = studyday - startmenstr, cycleday = (offset %% cyclelength) + 1 ) %>% ungroup() # 验证示例ID1的结果(匹配需求中的对应关系) df %>% filter(ID == 1, studyday %in% 1:7)
若startmenstr为二进制变量(月经当日=1,其余=0)
df <- df %>% group_by(ID) %>% mutate( # 从二进制变量提取月经开始的studyday startmenstr_day = studyday[startmenstr == 1], offset = studyday - startmenstr_day, cycleday = (offset %% cyclelength) + 1 ) %>% ungroup()
Python语言实现(pandas)
import pandas as pd import numpy as np # 构造示例数据 data = { 'ID': np.repeat([1, 2], 35), 'studyday': np.tile(range(1, 36), 2), 'cyclelength': np.concatenate([np.repeat(5, 35), np.repeat(7, 35)]), 'startmenstr': np.concatenate([np.repeat(2, 35), np.repeat(4, 35)]) } df = pd.DataFrame(data) # 定义分组计算函数 def compute_cycleday(group): offset = group['studyday'] - group['startmenstr'].iloc[0] group['cycleday'] = (offset % group['cyclelength'].iloc[0]) + 1 return group # 分组计算 df = df.groupby('ID').apply(compute_cycleday).reset_index(drop=True) # 验证示例ID1的结果 print(df[(df['ID'] == 1) & (df['studyday'].isin(range(1, 8)))])
若startmenstr为二进制变量
def compute_cycleday_binary(group): # 从二进制变量提取月经开始的studyday startmenstr_day = group[group['startmenstr'] == 1]['studyday'].iloc[0] offset = group['studyday'] - startmenstr_day group['cycleday'] = (offset % group['cyclelength'].iloc[0]) + 1 return group df = df.groupby('ID').apply(compute_cycleday_binary).reset_index(drop=True)
内容的提问来源于stack exchange,提问作者rororo
相关产品推荐
相关产品推荐

