R语言 从值行中提取虚拟变量

h5qlskok  于 2023-05-04  发布在  其他
关注(0)|答案(3)|浏览(202)

我有一个相当大的分隔数据集,列出了与这些合成数据类似的行中的个体特征:

id; ICD_Codes
1; F10.10; F11.21; F31.81
2; G89.29; M54.5; F31.4; F11.21; F17.200; F43.10; Z72.0
3; F14.10; F17.200; F31.81; F31.32; F10.21

(And是的,每行的“列”数各不相同)
我想从中提取一系列虚拟代码,每个ICD_Codes值一个,并使用给定个体是否呈现该值来填充这些虚拟变量,即:
| 身份证| F10.10 | F10.21 | F11.21 | F14.10 | F17.200 | F31.32 |F31.4| F31.81 | F43.10 | G89.29 |M54.5|Z72.0|
| --------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|
| 1|1|0|1|0|0|0|0|1|0|0|0|0|
| 二|0|0|1|0|1|0|1|0|1|1|1|1|
| 三|0|1|0|1|1|1|0|1|0|0|0|0|
或者,作为R Dataframe :

df <- data.frame(id = c(1, 2, 3),
                 F10.10 = c(1, 0, 0),
                 F10.21 = c(0, 0, 1),
                 F11.21 = c(1, 1, 0),
                 F14.10 = c(0, 0, 1),
                 F17.200 = c(0, 1, 1),
                 F31.32 = c(0, 0, 1),
                 F31.4 = c(0, 1, 0),
                 F31.81 = c(1, 0, 1),
                 F43.10 = c(0, 1, 0),
                 G89.29 = c(0, 1, 0),
                 M54.5 = c(0, 1, 0),
                 Z72.0 = c(0, 1, 0)
                 )

我想不出简单的方法来做到这一点(任何地方,包括在R中),但肯定有办法!
我将感激任何帮助这样做。

piwo6bdm

piwo6bdm1#

假设您没有将数据导入R中,我们可以使用read.table将数据作为单列读取(选择一个随机的sep符号,您确定不会出现在数据中)。
然后将idICD_Codes分成两列,并使用fastDummies::dummy_cols()创建虚拟变量。最后rename删除列前缀以适合您想要的输出。

library(dplyr)
library(tidyr)
library(fastDummies)

df <- read.table(text = "id; ICD_Codes
1; F10.10; F11.21; F31.81
2; G89.29; M54.5; F31.4; F11.21; F17.200; F43.10; Z72.0
3; F14.10; F17.200; F31.81; F31.32; F10.21", sep = "@", header = T)

df %>% 
  separate_wider_delim("id..ICD_Codes", names = c("id", "ICD_Codes"), delim = "; ", too_many = "merge") %>% 
  dummy_cols("ICD_Codes", remove_selected_columns = T, split = ";") %>% 
  rename_with(~sub("ICD_Codes_", "", .x))

# A tibble: 3 × 13
  id    F10.10 F11.21 F31.81 F14.10 F17.200 F31.32 F10.21 G89.29 M54.5 F31.4 F43.10 Z72.0
  <chr>  <int>  <int>  <int>  <int>   <int>  <int>  <int>  <int> <int> <int>  <int> <int>
1 1          1      1      1      0       0      0      0      0     0     0      0     0
2 2          0      1      0      0       1      0      0      1     1     1      1     1
3 3          0      0      1      1       1      1      1      0     0     0      0     0
kt06eoxx

kt06eoxx2#

不使用额外的包,您可以使用readLinesstrsplit。然后使用outer进行交叉grepl

read <- readLines(textConnection('id; ICD_Codes
1; F10.10; F11.21; F31.81
2; G89.29; M54.5; F31.4; F11.21; F17.200; F43.10; Z72.0
3; F14.10; F17.200; F31.81; F31.32; F10.21'))

read <- lapply(read, \(x) el(strsplit(x, split=';\\s*')))
icd <- sort(unique(unlist(lapply(read[-1], \(x) x[-1]))))
o <- t(outer(icd, read[-1], Vectorize(\(sprintf('^%s$', x), y) any(grepl(x, y)))))
data.frame(id=sapply(read[-1], `[`, 1), `colnames<-`(+o, icd))
#   id F10.10 F10.21 F11.21 F14.10 F17.200 F31.32 F31.4 F31.81 F43.10 G89.29 M54.5 Z72.0
# 1  1      1      0      1      0       0      0     0      1      0      0     0     0
# 2  2      0      0      1      0       1      0     1      0      1      1     1     1
# 3  3      0      1      0      1       1      1     0      1      0      0     0     0
  • 注意:* 对于您的真实的数据,您可能需要使用readLines(<path>)

有证据表明它比tidyverse解决方案快得多:

# Unit: microseconds
#     expr       min         lq      mean    median        uq       max neval cld
#   jay.sf   965.285   994.9295  1264.239  1089.907  1124.969  16915.81   100  a 
# benson23 17309.835 17533.8145 20036.727 17822.965 18763.764 159236.18   100   b
hrysbysz

hrysbysz3#

使用mtabulate即可

library(qdapTools)
cbind(id = sub(";.*", "", df[[1]]),
   mtabulate(strsplit(sub("^\\d+;\\s+", "", df[[1]]), ";\\s*")))
  • 输出
id F10.10 F10.21 F11.21 F14.10 F17.200 F31.32 F31.4 F31.81 F43.10 G89.29 M54.5 Z72.0
1  1      1      0      1      0       0      0     0      1      0      0     0     0
2  2      0      0      1      0       1      0     1      0      1      1     1     1
3  3      0      1      0      1       1      1     0      1      0      0     0     0

相关问题