首页 > 解决方案 > 如何为数据框 A 中存在的列的每个唯一值在数据框 B 中创建一个新列?

问题描述

我有一个dfA包含约 300 个条件的数据框,每个条件都有很多行,其中包含与之关联的诊断代码。

Condition <- as.character(c("COPD", "COPD", "COPD", "COPD", "HIV", "HIV", "HIV", "Sepsis", "Sepsis", "Sepsis", "Sepsis", "Sepsis"))
Code <- as.character(c("6A61.00", "8BPT.00", "8BPT000", "8BPT100", "E2E0.00", "E2E0100", "E2E0z00", "E2E1.00", "E2E2.00", "E2Ey.00", "E2Ez.00", "Eu84400"))
dfA <- data.frame(Condition, Code)
dfA
   Condition    Code
1       COPD 6A61.00
2       COPD 8BPT.00
3       COPD 8BPT000
4       COPD 8BPT100
5        HIV E2E0.00
6        HIV E2E0100
7        HIV E2E0z00
8     Sepsis E2E1.00
9     Sepsis E2E2.00
10    Sepsis E2Ey.00
11    Sepsis E2Ez.00
12    Sepsis Eu84400

我还有一个数据框dfB,每行有几个健康事件。这些事件用诊断代码标识。

Event <- as.double(1:12)
Code2 <- as.character(c("6A61.00", "Eu90z00", "8BPT000", "8BPT100", "Eu90111", "E2E0100", "E2E0z00", "E2E1.00", "E2E2.00", "Eu90z11", "Eu90z12", "Eu9y700"))
dfB <- data.frame(Event, Code2)
dfB
      Event   Code2
1      1 6A61.00
2      2 Eu90z00
3      3 8BPT000
4      4 8BPT100
5      5 Eu90111
6      6 E2E0100
7      7 E2E0z00
8      8 E2E1.00
9      9 E2E2.00
10    10 Eu90z11
11    11 Eu90z12
12    12 Eu9y700

我想在每个唯一条件(请注意,每个唯一条件有多行)的命名中创建一个column用于dfB标识每个. 这个想法是 - 例如,如果 in 中的一行包含存在于 中的诊断代码,那么in将接收值,否则,。例如:dfAdfAConditiondfBCondition HIVcolumn HIVdfB10

dfB$"COPD" <- 0
dfB$"COPD"[which(dfB$Code2 %in% (dfA$Code[which(dfA$Condition== "COPD")]))] <- 1

dfB$"HIV" <- 0
dfB$"HIV"[which(dfB$Code2 %in% (dfA$Code[which(dfA$Condition== "HIV")]))] <- 1

dfB$"Sepsis" <- 0
dfB$"Sepsis"[which(dfB$Code2 %in% (dfA$Code[which(dfA$Condition== "Sepsis")]))] <- 1
    
dfB
      Event   Code2 COPD HIV Sepsis
1      1 6A61.00    1   0      0
2      2 Eu90z00    0   0      0
3      3 8BPT000    1   0      0
4      4 8BPT100    1   0      0
5      5 Eu90111    0   0      0
6      6 E2E0100    0   1      0
7      7 E2E0z00    0   1      0
8      8 E2E1.00    0   0      1
9      9 E2E2.00    0   0      1
10    10 Eu90z11    0   0      0
11    11 Eu90z12    0   0      0
12    12 Eu9y700    0   0      0

我希望dfB为. column_ 但是,我不想为每个条件单独创建一个,因为我有 300 个条件。有没有更好的方法来优化一段代码以一次为每个唯一的我创建 300 ?需要以.ConditiondfAcolumncolumnsdfBConditiondfAcolumnsConditions

非常感谢您的帮助!

标签: rfunctionvariablesvector

解决方案


原始问题
在原始问题中,OP 在其全局环境中有 300 个“代码”向量,每个向量都以特定条件命名。

原始答案
与其他任何解决方案一样,此解决方案容易出错,因为您将 CID-10 代码存储为向量的方法很脆弱。例如,如果您的全局环境中有其他向量,则可能很难正确处理。

由于您感兴趣的向量都是字符,我们可以首先创建一个字符向量列表:

library(dplyr)
library(purrr)

list_of_CID_10<-mget(ls())%>%keep(is.character)
list_of_CID_10
$COPD
[1] "6A61.00" "8BPT.00" "8BPT000" "8BPT100"

$HIV
[1] "E2E0.00" "E2E0100" "E2E0z00"

$Sepsis
[1] "E2E1.00" "E2E2.00" "E2Ey.00" "E2Ez.00" "Eu84400"

#除此之外keep(is.character),您可能还需要使用更复杂的逻辑来过滤掉不需要的字符向量,例如@G 的建议。Grothendieck,按大小或使用正则表达式。就像是:

list_of_CID_10<-mget(ls())%>%
keep(all(str_detect(., "[A-Za-z]+[0-9]|[0-9]+[A-Za-z]+")) & all(str_length(.)==7))

第二步,遍历这个列表并调用(df$code %in% .x)

diagnoses<-map_dfc(list_of_CID_10, ~as.integer(df$Code %in% .x))
diagnoses

# A tibble: 12 x 3
    COPD   HIV Sepsis
   <int> <int>  <int>
 1     1     0      0
 2     0     0      0
 3     1     0      0
 4     1     0      0
 5     0     0      0
 6     0     1      0
 7     0     1      0
 8     0     0      1
 9     0     0      1
10     0     0      0
11     0     0      0
12     0     0      0

这可以很容易地附加到您的原始数据框:

> cbind(df, diagnoses)
   Event    Code COPD HIV Sepsis
1      1 6A61.00    1   0      0
2      2 Eu90z00    0   0      0
3      3 8BPT000    1   0      0
4      4 8BPT100    1   0      0
5      5 Eu90111    0   0      0
6      6 E2E0100    0   1      0
7      7 E2E0z00    0   1      0
8      8 E2E1.00    0   0      1
9      9 E2E2.00    0   0      1
10    10 Eu90z11    0   0      0
11    11 Eu90z12    0   0      0
12    12 Eu9y700    0   0      0

您可以在一次调用中完成所有操作,无需中间对象:

mget(ls())%>%keep(is.character)%>%
        map_dfc(~as.integer(df$Code %in% .x))%>%
        cbind(df, .)

更新的问题
在更新的版本中,OP 将其代码按行存储在数据框中。

答案
使用 OPs 编辑中的数据框中的代码,我会将代码的数据框拆分为疾病列表,而不是使用与原始答案中类似的方法:

split(dfA$Code, dfA$Condition)%>%
        map_dfc(~as.integer(dfB$Code2 %in% .x))%>%
        cbind(dfB, .)

#OR, using `dplyr::group_split()`

dfA%>%group_by(Condition)%>%
        group_split()%>%
        set_names(unique(dfA$Condition))%>%
        map_dfc(~as.integer(dfB$Code2 %in% .x$Code))%>%
        cbind(dfB, .)

推荐阅读