根据R中的规范数据添加一列
Adding a column according to norm data in R
我有一个长格式的纵向数据集,长度约为 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
我想创建一个新列 "cutoff",其值为 "Normal" 或 "Impaired",因为我的结果数据 "score" 有一个截止分数,表明根据常模存在损伤。根据性别、教育程度(受教育年限)和年龄,常模由不同的 -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 文件而不是对其进行硬编码,尽管您可能需要稍微不同地构建它。我会像数据集一样构造它,包含 Sex、Edu、Age、Mean、SD、-1.5SD 等列,将其导入 R,然后在 Sex+Edu+Age 上进行左外连接:
merge(x = long_df, y = norm_df, by = c("Sex", "Edu(yr)", "Age"), all.x = TRUE)
然后就可以直接比较列了
如果我没理解错的话,OP 想在他的数据集中标记某种类型的异常值。所以,这里有两个任务:
- 计算每组
sex
、年龄类别 agecat
和教育类别 mean(score)
、sd(score)
和截止值 mean(score) - 1.5 * sd(score)
edcat
.
- 查找
score
低于特定组的截止值的所有行。
正如已经提到的,第二步可以通过non-equi join来实现。
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)
我有一个长格式的纵向数据集,长度约为 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
我想创建一个新列 "cutoff",其值为 "Normal" 或 "Impaired",因为我的结果数据 "score" 有一个截止分数,表明根据常模存在损伤。根据性别、教育程度(受教育年限)和年龄,常模由不同的 -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 文件而不是对其进行硬编码,尽管您可能需要稍微不同地构建它。我会像数据集一样构造它,包含 Sex、Edu、Age、Mean、SD、-1.5SD 等列,将其导入 R,然后在 Sex+Edu+Age 上进行左外连接:
merge(x = long_df, y = norm_df, by = c("Sex", "Edu(yr)", "Age"), all.x = TRUE)
然后就可以直接比较列了
如果我没理解错的话,OP 想在他的数据集中标记某种类型的异常值。所以,这里有两个任务:
- 计算每组
sex
、年龄类别agecat
和教育类别mean(score)
、sd(score)
和截止值mean(score) - 1.5 * sd(score)
edcat
. - 查找
score
低于特定组的截止值的所有行。
正如
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)