r - R中基于多个条件的查找表

标签 r lookup lookup-tables

谢谢你看我的问题!

我有以下(虚拟)数据用于患者在 3 项任务中的表现:

patient_df = data.frame(id = seq(1:5),
                        age = c(30,72,46,63,58),
                        education = c(11, 22, 18, 12, 14),
                        task1 = c(21, 28, 20, 24, 22),
                        task2 = c(15, 15, 10, 11, 14), 
                        task3 = c(82, 60, 74, 78, 78))
> patient_df
  id age education task1 task2 task3
1  1  30        11    21    15    82
2  2  72        22    28    15    60
3  3  46        18    20    10    74
4  4  63        12    24    11    78
5  5  58        14    22    14    78

我还有以下(虚拟)查找表,用于基于年龄和教育的临界值来定义患者在每项任务中的表现受损或未受损:
cutoffs = data.frame(age = rep(seq(from = 35, to = 70, by = 5), 2),
                     education = c(rep("<16", 8), rep(">=16",8)),
                     task1_cutoff = c(rep(24, 16)),
                     task2_cutoff = c(11,11,11,11,10,10,10,10,9,13,13,13,13,12,12,11),
                     task3_cutoff = c(rep(71,8), 70, rep(74,2), rep(73, 5)))
> cutoffs
   age education task1_cutoff task2_cutoff task3_cutoff
1   35       <16           24           11           71
2   40       <16           24           11           71
3   45       <16           24           11           71
4   50       <16           24           11           71
5   55       <16           24           10           71
6   60       <16           24           10           71
7   65       <16           24           10           71
8   70       <16           24           10           71
9   35      >=16           24            9           70
10  40      >=16           24           13           74
11  45      >=16           24           13           74
12  50      >=16           24           13           73
13  55      >=16           24           13           73
14  60      >=16           24           12           73
15  65      >=16           24           12           73
16  70      >=16           24           11           73

我的目标是在 Patient_df 中创建 3 个新变量,用二进制指示器指示患者在每项任务中是否受损。例如,对于patient_df中的id=1,他们的年龄<=35,他们的教育<16年,因此task1的截止值为24,task2的截止值为11,task3的截止值为为 71,因此低于这些值的分数将表示受损。

我想通过引用截止数据集中与年龄和教育相关的截止值来为每个 id 执行此操作,以便结果如下所示:
> goal_patient_df
  id age education task1 task2 task3 task1_impaired task2_impaired task3_impaired
1  1  30        11     21     15     82               1               1               0
2  2  72        22     28     15     60               0               0               1
3  3  46        18     20     10     74               1               1               0
4  4  63        12     24     11     78               1               0               0
5  5  58        14     22     14     78               1               0               0

实际上,我的 Patient_df 有 600 多个患者,并且有 7 个以上的任务,每个任务都具有与年龄和教育相关的截止值,因此非常感谢这样做的“干净”方式!我现在能想到的唯一替代方法是编写一吨 if_else 语句或 case_whens,对于使用我的代码的其他人来说,这不会令人难以置信地重现:(

先感谢您!

最佳答案

我建议同时放置您的查找表和 patient_df长格式的数据框。我认为这可能更容易管理多个任务。

您的 education列是数字;因此转换为字符“<16”或“>=16”将有助于查找表中的匹配。

使用 fuzzy_inner_join将数据与任务和教育完全匹配的查找表匹配 ==但是 age将在 age_low 之间和 age_high如果您为每个查找表行指定一个年龄范围。

最后,impaired计算比较来自特定任务的两个数据帧的值。

请注意输出,id缺少 1 个,因为不在查找表的年龄范围内。您可以向该表添加更多行来解决此问题。

library(tidyverse)
library(fuzzyjoin)

cutoffs_long <- cutoffs %>%
  pivot_longer(cols = starts_with("task"), names_to = "task", values_to = "cutoff_value", names_pattern = "task(\\d+)") %>%
  mutate(age_low = age, 
         age_high = age + 4) %>%
  select(-age)

patient_df %>%
  pivot_longer(cols = starts_with("task"), names_to = "task", values_to = "patient_value", names_pattern = "(\\d+)") %>%
  mutate(education = ifelse(education < 16, "<16", ">=16")) %>%
  fuzzy_inner_join(cutoffs_long, by = c("age" = "age_low", "age" = "age_high", "education", "task"), match_fun = list(`>=`, `<=`, `==`, `==`)) %>%
  mutate(impaired = +(patient_value < cutoff_value))

输出
# A tibble: 12 x 11
      id   age education.x task.x patient_value education.y task.y cutoff_value age_low age_high impaired
   <int> <dbl> <chr>       <chr>          <dbl> <chr>       <chr>         <dbl>   <dbl>    <dbl>    <int>
 1     2    72 >=16        1                 28 >=16        1                24      70       74        0
 2     2    72 >=16        2                 15 >=16        2                11      70       74        0
 3     2    72 >=16        3                 60 >=16        3                73      70       74        1
 4     3    46 >=16        1                 20 >=16        1                24      45       49        1
 5     3    46 >=16        2                 10 >=16        2                13      45       49        1
 6     3    46 >=16        3                 74 >=16        3                74      45       49        0
 7     4    63 <16         1                 24 <16         1                24      60       64        0
 8     4    63 <16         2                 11 <16         2                10      60       64        0
 9     4    63 <16         3                 78 <16         3                71      60       64        0
10     5    58 <16         1                 22 <16         1                24      55       59        1
11     5    58 <16         2                 14 <16         2                10      55       59        0
12     5    58 <16         3                 78 <16         3                71      55       59        0

关于r - R中基于多个条件的查找表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62352017/

相关文章:

django-models - 如何将 'contains' 与 manytomany 字段一起使用?

python - Databricks:如何从 R Dataframe 切换到 Pandas Dataframe(R 到 python 在同一笔记本中)

r - 需要规则时使用的基本包。指定包不起作用

r - 非转义由 R XML 包生成的解析字符串?

R 不能将 NaN 转换为 NA

java - 具有两种 O(1) 查找方式的数据结构。哈希表?

c++ - 使用模板构建静态(但复杂)的查找表

ruby-on-rails - 在 Rails 中实现查找表

c - 在非常长的字符串中查找频率的最佳方法

python - 如何将 Python 列表格式化为已初始化的 C 数组?