Skip to content

Commit 419b65f

Browse files
Create NHS England CKD algorithm
1 parent a4a8371 commit 419b65f

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed

NHS England CKD algorithm

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#CKD IS STAGED HERE BASED ON MAINTENANCE OF EACH EGFR LEVEL FOR A MINIMUM OF 3 MONTHS
2+
#CKD HAS BEEN DERIVED HERE FROM CKD-EPI EGFR
3+
4+
load("crea.repv12.rda") #table featuring 1 row per patient per day with maximum creatinine retained
5+
load ("sir.data.rda") #long format input file with 1 row per event entry
6+
7+
#Reduce dataset to individuals eligible for CKD and AKI staging before looping;
8+
#Identify potential creatinine based CKD patients (individuals with any egfr<60)
9+
#Isolate the first qualifying test for each patient
10+
11+
crea.rep$KDmarkE<-ifelse(!is.na(crea.rep$CKDEPIeGFR) & crea.rep$CKDEPIeGFR<60,1,0)
12+
CKsE<-crea.rep[crea.rep$KDmarkE==1,c("PatientID","EntryDate","KDmarkE")] #Kidney Injury flagged tests
13+
14+
#Create a dataset including all data from patients with at least 1 KD flag:
15+
CKpotE<-crea.rep[crea.rep$PatientID %in% CKsE$PatientID,]
16+
CKpotE$EntryDate2<-as.Date(as.character(CKpotE$EntryDate),format="%Y%m%d")
17+
18+
#Mark a 90 day lookback period
19+
CKpotE$EntryDate1<-as.Date(as.character(CKpotE$EntryDate),format="%Y%m%d")-90
20+
CKpotE<-CKpotE[,c("PatientID","event.date","KDmarkE","EntryDate1","EntryDate2","CKDEPIeGFR")]
21+
22+
############################################################################################## CHECKED
23+
#Diagnose CKD
24+
#If eGFR under 60 is not sustained for 90 days, recode KDmark as 0
25+
for (i in 1:length(CKpotE$PatientID)){
26+
CKpotE$CKDE[i]<-min(crea.rep$KDmarkE[crea.rep$PatientID==CKpotE$PatientID[i] &
27+
crea.rep$event.date>CKpotE$EntryDate1[i] & crea.rep$event.date<=CKpotE$EntryDate2[i]])
28+
CKpotE$MaxCKDE[i]<-max(crea.rep$CKDEPIeGFR[crea.rep$PatientID==CKpotE$PatientID[i] &
29+
crea.rep$event.date>CKpotE$EntryDate1[i] & crea.rep$event.date<=CKpotE$EntryDate2[i]])
30+
}
31+
#CKD is 1 if the test qualifies and there is no normal test within 3 months prior
32+
#At this stage some are temporarily falsely positively identified that have no lookback test
33+
34+
#Near date match EntryDate1 (90 days prior date)- to entries from the full dataset
35+
#neardate preferably matches to a prior entry if one is available
36+
#if the closest match is before EntryDate1 (data from more than 90 days prior available), retain row.
37+
indx1<-neardate(CKpotE$PatientID,crea.rep$PatientID,CKpotE$EntryDate1,crea.rep$event.date,best="prior",nomatch=NA_integer_)
38+
CKpotE$Lookback<-crea.rep[indx1,"event.date"]
39+
CKpotE$CKDGEStage<-ifelse(CKpotE$Lookback<=CKpotE$EntryDate1 & CKpotE$CKDE==1,1,0)
40+
CKpotE<-CKpotE[CKpotE$CKDGEStage==1,]
41+
#CKpot is a subset table of CKD qualifying tests and their markers to be merged onto crea.rep
42+
CKpotE<-unique(CKpotE)
43+
crea.rep<-merge(crea.rep,CKpotE[,c(1,2,8:10)],all.x=TRUE)
44+
crea.rep$CKDGEStage<-ifelse(!is.na(crea.rep$CKDGEStage),2,0)
45+
#Stage 1 is skipped here as it cannot be identified from creatinine only, start by coding all as stage 2
46+
table(crea.rep$CKDGEStage)
47+
48+
crea.rep$CKDGEStage<-ifelse(crea.rep$CKDGEStage>0&crea.rep$MaxCKDE>=30&crea.rep$MaxCKDE<45,3.5,crea.rep$CKDGEStage)
49+
crea.rep$CKDGEStage<-ifelse(crea.rep$CKDGEStage>0&crea.rep$MaxCKDE>=45&crea.rep$MaxCKDE<60,3,crea.rep$CKDGEStage)
50+
crea.rep$CKDGEStage<-ifelse(crea.rep$CKDGEStage>0&crea.rep$MaxCKDE>=15&crea.rep$MaxCKDE<30,4,crea.rep$CKDGEStage)
51+
crea.rep$CKDGEStage<-ifelse(crea.rep$CKDGEStage>0&crea.rep$MaxCKDE<15,5,crea.rep$CKDGStage)
52+
crea.rep$CKDGEStage<-ifelse(is.na(crea.rep$CKDGEStage),0,crea.rep$CKDGEStage)
53+
table(crea.rep$CKDGEStage)
54+
55+
#can replace with dplyr
56+
#Recode to KDIGO
57+
crea.rep$CKDGEStage<-ifelse(crea.rep$CKDGEStage==3.5,paste("3b"),paste(crea.rep$CKDGEStage))
58+
crea.rep$MaxCKDGEStage<-ifelse(crea.rep$MaxCKDGEStage==3.5,paste("3b"),paste(crea.rep$MaxCKDGEStage))
59+
60+
61+
#########################################################################################################
62+
63+
#Mark start of first CKD diagnosis based on creatinine only
64+
CKs<-CKpot %>%
65+
group_by(PatientID)%>%
66+
slice(which.min(EntryDate1)) %>%
67+
as.data.frame
68+
CKs<-CKs[,c(1,2)]
69+
names(CKs)<-c("PatientID","CKDG_Date")
70+
crea.rep<-merge(crea.rep,CKs,all.x=TRUE)
71+
crea.rep$TimeSinceCKD<-difftime(as.Date(as.character(crea.rep$EntryDate),format="%Y%m%d"),crea.rep$CKDG_Date,unit="days")
72+
########################################################################################################
73+
74+
#Incorporate Urine Albumin to creatinine ratio data if available:
75+
crea.rep$CKDAStage<-ifelse(crea.rep$UACratio<3,1,0)
76+
crea.rep$CKDAStage<-ifelse(crea.rep$UACratio>=3&crea.rep$UACratio<30&!crea.rep$CKDGStage=="0",2,crea.rep$CKDAStage)
77+
crea.rep$CKDAStage<-ifelse(crea.rep$UACratio>30&!crea.rep$CKDGStage=="0",3,crea.rep$CKDAStage)
78+
79+
#Stage CKD based on both UAC and creatinine data:
80+
crea.rep$CKDGStage<-crea.rep$CKDGEStage
81+
crea.rep$CKDPrognosis<-crea.rep$CKDGStage
82+
crea.rep$CKDPrognosis<-ifelse(crea.rep$CKDGStage<=2 & crea.rep$CKDAStage==2,1,crea.rep$CKDPrognosis)
83+
crea.rep$CKDPrognosis<-ifelse(crea.rep$CKDGStage<=2 & crea.rep$CKDAStage==3,2,crea.rep$CKDPrognosis)
84+
crea.rep$CKDPrognosis<-ifelse(crea.rep$CKDGStage>=3,3,crea.rep$CKDPrognosis)
85+
crea.rep$CKDPrognosis<-ifelse(crea.rep$CKDGStage==3.5 & crea.rep$CKDAStage==1,2,crea.rep$CKDPrognosis)
86+
crea.rep$CKDPrognosis<-ifelse(crea.rep$CKDGStage==3 & crea.rep$CKDAStage==1,1,crea.rep$CKDPrognosis)
87+
crea.rep$CKDPrognosis<-ifelse(crea.rep$CKDGStage==3 & crea.rep$CKDAStage==2,2,crea.rep$CKDPrognosis)
88+
89+
#Where CKD diagnosed based on creatinine, add metric for summarised eGFR range for further phenotyping
90+
crea.rep$CustomeGFR<-ifelse(crea.rep$CKDPrognosis>0 &crea.rep$MDRDeGFR>=60 & crea.rep$MDRDeGFR<90,1,NA)
91+
crea.rep$CustomeGFR<-ifelse(crea.rep$CKDPrognosis>0 & crea.rep$MDRDeGFR>=60 & crea.rep$MDRDeGFR<90,1,NA)
92+
crea.rep$CustomeGFR<-ifelse(crea.rep$CKDPrognosis>0 &crea.rep$MDRDeGFR>=45 & crea.rep$MDRDeGFR<60,2,crea.rep$CustomeGFR)
93+
crea.rep$CustomeGFR<-ifelse(crea.rep$CKDPrognosis>0 &crea.rep$MDRDeGFR>=30 & crea.rep$MDRDeGFR<45,3,crea.rep$CustomeGFR)
94+
crea.rep$CustomeGFR<-ifelse(crea.rep$CKDPrognosis>0 &crea.rep$MDRDeGFR>=15 & crea.rep$MDRDeGFR<30,4,crea.rep$CustomeGFR)
95+
crea.rep$CustomeGFR<-ifelse(crea.rep$CKDPrognosis>0 &crea.rep$MDRDeGFR<15,5,crea.rep$CustomeGFR)
96+
97+
98+
###################################################################################

0 commit comments

Comments
 (0)