根据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 想在他的数据集中标记某种类型的异常值。所以,这里有两个任务:

  1. 计算每组 sex、年龄类别 agecat 和教育类别 mean(score)sd(score) 和截止值 mean(score) - 1.5 * sd(score) edcat.
  2. 查找 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)