我已经很久没有在R中操作数据集了,到目前为止,我一直在excel中手动操作,但这很麻烦,因为我的数据集不小!
我对以下变量感兴趣:
PATIENT_ID-在数据集中多次出现
CYCLE_ID-唯一
CYCLE_NO-按时间顺序从每个PATIENT_ID 1开始
CALC_ACT-是或否
我需要的是创建一个符合以下标准的新数据集:对于单个PATIENT_ ID;是";和其中CALC_ ACT=="1"的一行;否";。
CALC_ ACT==";是";行必须具有比CALC_ ACT==;否";一行
我只需要每个PATIENT_ID匹配一个,忽略其余的。
对于一个已经多年没有做任何编程的人来说,这件事的复杂性让我头疼!!!
提前感谢
在下面的例子中,应该只保留第3行和第4行。第4行(CYCLE_NO==6(是CALC_ACT第一次为"是",上一个循环为"否"。PATIENT_ID 222和456的行不符合标准,因为它们需要同时具有CALC_ACT的"是"one_answers"否"二者。希望这是有意义的。。。
PatientData <- data.frame(PATIENT_ID = c(123, 123, 123, 123, 123, 222, 222, 222, 456, 456), CYCLE_ID = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), CYCLE_NO = c(1, 3, 4, 6, 7, 2, 3, 4, 1, 2), CALC_ACT = c("Yes", "No", "No", "Yes", "Yes", "No", "No", "No", "Yes", "Yes"))
PatientData
PATIENT_ID CYCLE_ID CYCLE_NO CALC_ACT
1 123 1 1 Yes
2 123 2 3 No
3 123 3 4 No
4 123 4 6 Yes
5 123 5 7 Yes
6 222 6 2 No
7 222 7 3 No
8 222 8 4 No
9 456 9 1 Yes
10 456 10 2 Yes
这里有一个函数,它应该按照逻辑工作。
return_rows <- function(CALC_ACT, CYCLE_NO) {
#indices of 'yes' rows
yes_ind <- which(CALC_ACT == 'Yes')
#indices of 'no' rows
no_ind <- which(CALC_ACT == 'No')
#Only if both the yes and no rows are present else don't select any row
if(length(yes_ind) && length(no_ind)) {
#Get the minimum length of yes and no rows
n <- min(length(yes_ind), length(no_ind))
#Get the first value where yes no has higher CYCLE_NO than the no row
ind <- which(CYCLE_NO[yes_ind[1:n]] > CYCLE_NO[no_ind[1:n]])[1]
#Return the corresponding index
sort(c(yes_ind[ind], no_ind[ind]))
} else 0
}
将此功能应用于每个PATIENT_ID
-
PatientData %>%
arrange(PATIENT_ID, CYCLE_NO) %>%
group_by(PATIENT_ID) %>%
slice(return_rows(CALC_ACT, CYCLE_NO)) %>%
ungroup
# PATIENT_ID CYCLE_ID CYCLE_NO CALC_ACT
# <dbl> <dbl> <dbl> <chr>
#1 123 3 4 No
#2 123 4 6 Yes
此代码应能在中工作
library(data.table)
PatientData <- data.frame(PATIENT_ID = c(123, 123, 123, 123, 123, 222, 222, 222, 456, 456), CYCLE_ID = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
CYCLE_NO = c(1, 3, 4, 6, 7, 2, 3, 4, 1, 2), CALC_ACT = c("Yes", "No", "No", "Yes", "Yes", "No", "No", "No", "Yes", "Yes"))
d1 = data.table(PatientData[order(PatientData$PATIENT_ID, PatientData$CYCLE_NO),])
d1$CALC_ACT1 = ifelse(d1$CALC_ACT == 'Yes',1,0)
d1[ , diff := CALC_ACT1 - shift(CALC_ACT1), by = PATIENT_ID]
out = d1[c(which(d1$diff == 1), (which(d1$diff == 1) -1)),]
out