我有一个长形式的纵向数据集,长度约为 2800,总共有大约 400 名参与者。这是我的数据示例。
# ID wave score sex age edu
#1 1001 1 28 1 69 12
#2 1001 2 27 1 70 12
#3 1001 3 28 1 71 12
#4 1001 4 26 1 72 12
#5 1002 1 30 2 78 9
#6 1002 3 30 2 80 9
#7 1003 1 30 2 65 16
#8 1003 2 30 2 66 16
#9 1003 3 29 2 67 16
#10 1003 4 28 2 68 16
#11 1004 1 22 2 85 4
#12 1005 1 20 2 60 9
#13 1005 2 18 1 61 9
#14 1006 1 22 1 74 9
#15 1006 2 23 1 75 9
#16 1006 3 25 1 76 9
#17 1006 4 19 1 77 9
我想创建一个值为"正常"或"受损"的新列"截止",因为我的结果数据"分数"有一个临界分数,指示根据规范的损害。该规范由根据性别、教育(教育年份)和年龄的不同 -1SD 措施(截止点)组成。
以下是我目前正在做的事情,自己检查一个 excel 文件并根据三个条件输入相应的截止分数。首先,我不确定我是否创建了正确的列。
data$cutoff <- ifelse(data$sex==1 & data$age<70
& data$edu<3
& data$score<19.91, "Impaired", "Normal")
data$cutoff <- ifelse(data$sex==2 & data$age<70
& data$edu<3
& data$score<18.39, "Impaired", "Normal")
此外,我想知道我是否可以导入一个说明规范的 excel 文件,并根据其中的值创建一个列。
Excel 文件的结构如下所示。
# Sex Male Female
#60-69 Edu(yr) 0-3 4-6 7-12 13>= 0-3 4-6 7-12 13>=
#Age Number 22 51 119 72 130 138 106 51
# Mean 24.45 26.6 27.06 27.83 23.31 25.86 27.26 28.09
# SD 3.03 1.89 1.8 1.53 3.28 2.55 1.85 1.44
# -1.5SD' 19.92 23.27 23.76 24.8 18.53 21.81 23.91 25.15
#70-79 Edu(yr) 0-3 4-6 7-12 13>= 0-3 4-6 7-12 13>=
....
我创建了新列"agecat"和"educat",将每个ID分配到规范中使用的年龄和教育组。现在我想利用这些列,将其与上面 excel 文件的行和列相匹配。动机之一是创建一个代码,可以使用我的数据的测试分数进行进一步研究。
我认为您的ifelse
语句应该可以正常工作,但我肯定会导入 Excel 文件而不是硬编码它,尽管您可能需要稍微不同地构建它。我会像数据集一样构建它,包括性别、Edu、年龄、平均值、SD、-1.5SD 等列,将其导入 R,然后在+Edu+Age 上做一个左外连接:
merge(x = long_df, y = norm_df, by = c("Sex", "Edu(yr)", "Age"), all.x = TRUE)
然后,您可以直接比较列。
如果我理解正确,OP 希望在他的数据集中标记某种类型的异常值。因此,这里有两个任务:
- 计算每组
sex
、年龄类别agecat
和 edu 类别edcat
的统计信息mean(score)
、sd(score)
和截止值mean(score) - 1.5 * sd(score)
。 - 查找
score
低于特定组的截止值的所有行。
正如 hannes101 已经提到的,第二步可以通过非等连接来实现。
library(data.table)
# categorize age and edu (left closed intervals)
mydata[, c("agecat", "educat") := .(cut(age, c(seq(0, 90, 10), Inf), right = FALSE),
cut(edu, c(0, 4, 7, 13, Inf), right = FALSE))][]
# compute statistics
cutoffs <- mydata[, .(.N, Mean = mean(score), SD = sd(score),
m1.5SD = mean(score) - 1.5 * sd(score)),
by = .(sex, agecat, educat)]
# non-equi update join
mydata[, cutoff := "Normal"]
mydata[cutoffs, on = .(sex, agecat, educat, score < m1.5SD), cutoff := "Impaired"][]
mydata
ID wave score sex age edu agecat educat cutoff 1: 1001 1 28 1 69 12 [60,70) [7,13) Normal 2: 1001 2 27 1 70 12 [70,80) [7,13) Normal 3: 1001 3 28 1 71 12 [70,80) [7,13) Normal 4: 1001 4 26 1 72 12 [70,80) [7,13) Normal 5: 1002 1 30 2 78 9 [70,80) [7,13) Normal 6: 1002 3 30 2 80 9 [80,90) [7,13) Normal 7: 1003 1 33 2 65 16 [60,70) [13,Inf) Normal 8: 1003 2 32 2 66 16 [60,70) [13,Inf) Normal 9: 1003 3 31 2 67 16 [60,70) [13,Inf) Normal 10: 1003 4 24 2 68 16 [60,70) [13,Inf) Impaired 11: 1004 1 22 2 85 4 [80,90) [4,7) Normal 12: 1005 1 20 2 60 9 [60,70) [7,13) Normal 13: 1005 2 18 1 61 9 [60,70) [7,13) Normal 14: 1006 1 22 1 74 9 [70,80) [7,13) Normal 15: 1006 2 23 1 75 9 [70,80) [7,13) Normal 16: 1006 3 25 1 76 9 [70,80) [7,13) Normal 17: 1006 4 19 1 77 9 [70,80) [7,13) Normal 18: 1007 1 33 2 65 16 [60,70) [13,Inf) Normal 19: 1007 2 32 2 66 16 [60,70) [13,Inf) Normal 20: 1007 3 31 2 67 16 [60,70) [13,Inf) Normal 21: 1007 4 31 2 68 16 [60,70) [13,Inf) Normal ID wave score sex age edu agecat educat cutoff
在这个虚构的示例中,只有一行满足"Impaired"
条件。
同样,统计数据也相当稀疏:
cutoffs
sex agecat educat N Mean SD m1.5SD 1: 1 [60,70) [7,13) 2 23.00000 7.071068 12.39340 2: 1 [70,80) [7,13) 7 24.28571 3.147183 19.56494 3: 2 [70,80) [7,13) 1 30.00000 NA NA 4: 2 [80,90) [7,13) 1 30.00000 NA NA 5: 2 [60,70) [13,Inf) 8 30.87500 2.900123 26.52482 6: 2 [80,90) [4,7) 1 22.00000 NA NA 7: 2 [60,70) [7,13) 1 20.00000 NA NA
数据
OP 的示例数据集已在一组中进行了修改以进行演示。
library(data.table)
mydata <- fread("
# ID wave score sex age edu
#1 1001 1 28 1 69 12
#2 1001 2 27 1 70 12
#3 1001 3 28 1 71 12
#4 1001 4 26 1 72 12
#5 1002 1 30 2 78 9
#6 1002 3 30 2 80 9
#7 1003 1 33 2 65 16
#8 1003 2 32 2 66 16
#9 1003 3 31 2 67 16
#10 1003 4 24 2 68 16
#11 1004 1 22 2 85 4
#12 1005 1 20 2 60 9
#13 1005 2 18 1 61 9
#14 1006 1 22 1 74 9
#15 1006 2 23 1 75 9
#16 1006 3 25 1 76 9
#17 1006 4 19 1 77 9
#18 1007 1 33 2 65 16
#19 1007 2 32 2 66 16
#20 1007 3 31 2 67 16
#21 1007 4 31 2 68 16
", drop = 1L)