1

我以前在 SAS 工作,然后出于学术要求的原因决定转向 R。我的数据(healthdemo)是包含一些健康诊断代码(ICD-10)的健康数据,我想将这些代码分成不同的列。这是 str(healthdemo) 的一部分:

$ PATIENT_KEY     : int  7391510 7404298 7390196 7381208 7401691 7381223 7383005 10188634 7384574 7398317 ...
 $ ICDCODE         : Factor w/ 1125 levels "","H00","H00.0",..: 654 56 654 654 665 48 90 679 654 654 ...
 $ PATIENT_ID      : int  39387 50244 38388 27346 49922 27901 27867 61527 33186 45309 ...
 $ DATE_OF_BIRTH   : Factor w/ 14801 levels "","01/01/1000",..: 7506 10250 52 73 94 6130 85 2710 95 100 ...

ICDCODE 包含从 H00 到 J99 的多种疾病;首先,我将 ICDCODE 中的字母与数字分开

healthdemo$icd_char = substr(healthdemo$ICDCODE,1,1)
healthdemo$icd_num = substr(healthdemo$ICDCODE,2,2)

然后我通过这个函数创建了疾病列:

healthdemo$cvd = 0
healthdemo$ihd = 0
healthdemo$mi = 0
healthdemo$dys = 0
healthdemo$afib = 0
healthdemo$chf = 0

现在我想应用一个类似于这个 SAS 函数(我曾经使用过)的函数:

if icd_char = 'I' and 01 <= icd_num < 52 then cvd = 1;

if icd_char = 'I' and 20 <= icd_num <= 25 then ihd = 1;

if icd_char = 'I' and 21 <= icd_num <= 22 then mi = 1;

if icd_char = 'I' and 46 <= icd_num <= 49 then dys = 1;

if icd_char = 'I' and icd_num = 48 then afib = 1;

此函数将给每个患者分配给定的 ICD 字符和 ICD 编号到 cvd=1(例如)等等。

我尝试在 R 中使用这些函数,但它们对我不起作用:

healthdemo$cvd[healthdemo$icd_char == 'I' & 01 <= healthdemo$icd_num 
      & healthdemo$icd_num < 52 ] <- 1

还有这个

if (healthdemo$icd_char == "I" &  01 < = healthdemo$icd_num < 52  )
   {healthdemo$cvd <- 1} 

有人可以帮帮我吗?

4

4 回答 4

2

SAS 中 IF ... THEN >>> 的行为是通过使用 NOT if(...){...} 而是使用 ifelse(..., ..., ...) 来实现的。而且你不能使用表格a < var < b。此外,您还没有完全了解 R 编程的功能范式。

试试这个,而不是你的最后一句话:

healthdemo$cvd <- NA   # initialize to missing
healthdemo$cvd <- ifelse (healthdemo$icd_char == "I" & 
                           01 <= healthdemo$icd_num &
                           healthdemo$icd_num < 52 , 1, healthdemo$cvd ) 

请注意,表单:var <- ifelse(logicalvec, value, var)允许您进行选择性替换。旧值是默认值,只有逻辑向量中的“并行”值 TRUE 才会触发更改。

Robert Muenchen 写了一本题为“R for SAS and SPSS Users”的书。还有一个免费提供的草稿版本,大约 70 页长,应该通过网络搜索显示。

于 2012-11-05T14:20:52.340 回答
2

当我从 SAS 过渡到 R 进行与健康相关的研究时,我也遇到了类似的困难。我的解决方案是尽可能放弃“如果...那么”的方法,并利用 R 的一些独特的本地编程功能。这是解决您的问题的两种方法。

首先,您可以使用索引来查找和替换元素。以下是您描述的一些出院数据:

hosp<-read.csv(file="http://www.columbia.edu/~cjd11/charles_dimaggio/DIRE/resources/R/sparcsShort.csv",stringsAsFactors=F)
head(hosp)

假设我想确定曼哈顿的每一个与出生有关的诊断。我首先创建一个逻辑向量,为我的搜索条件返回一系列 TRUES 和 FALSES,然后按该逻辑向量索引我的数据框。在这种情况下,我还限制了我想要返回的列或变量:

myObs<-hosp$county==59 & hosp$pdx=="V3000 " #note space
myVars<-c("age", "sex", "disp")
myFile<-hosp[myObs,myVars]
head(myFile)

第二种,也许在计算上更优雅的方法是使用像“grep”这样的函数。假设您有兴趣识别所有物质滥用诊断,例如酒精滥用(291、303、305 和子代码)、阿片类药物、大麻、安非他明、致幻剂和可卡因(304 和相关子代码),或非特异性与药物滥用有关的诊断 (292)。在 SAS 中,您会写出某种较长的 if-then 语句(或更高效的数组):

#/*********************** SUBSTANCE ABUSE *****************/
#if pdx in /* use ICD9 codes to create diagnoses */ (’2910’,’2911’,’2912’,’2913’,’2914’,’2915’,
#   ’29181’,’29189’, ’2919’,’2920’,’29211’,’29212’,’2922’,’29281’,’29282’,’29283’, #........etc....,’30592’,’30593’)
#Then subst_ab=1; 
#Else subst_ab=0;

在 R 中,您可以改为编写:

substance<-grep("^291[0-9,0-9]|^292[0-9,0-9]|^303[0-9,0-9]|^304[0-9,0-9]^305[0-9,0-9]", hosp$pdx)
hosp$pdx[substance]
hosp$subsAb<-"No"
hosp$subsAb[substance]<-"Yes"
hosp$subsAb[1:100]

table(hosp$subsAb)
plot(table(hosp$subsAb))

library(ggplot2)
qplot(subsAb, age,data=hosp, alpha = I(1/50))

Tomas Aragon 为流行病学家写了一篇精彩的 R 介绍,详细介绍了这些方法。(http://www.medepi.net/docs/ph251d_fall2012_epir-chap01-04.pdf)

于 2012-11-06T12:47:12.107 回答
0

我想问题是icd_num由于不是数字。

使用以下命令创建此变量:

healthdemo$icd_num <- as.numeric(substr(healthdemo$ICDCODE, 2,
                                        nchar(healthdemo$ICDCODE)))

(如果你想去掉 后面的数字,用.代替。)as.numericas.integer

那么你的第一种方法应该有效:

healthdemo$cvd[healthdemo$icd_char == 'I' &
               01 <= healthdemo$icd_num &
               healthdemo$icd_num < 52 ] <- 1
于 2012-11-05T14:27:40.037 回答
0

我创建了icd包来解决这类问题。您可以使用标准疾病组,或创建自己的疾病组。然后它可以快速浏览您的所有代码并将疾病组分配给每个患者。它适用于 ICD-9 和 ICD-10 代码。

我发现纯文本处理(如grep之前的答案)既慢又不可靠。ICD 代码的记录方式有很多变化,例如,ICD-9 代码X91.9等价于 0919。数十万行的字符串处理对于我有效地使用 R 函数来说太慢了,所以我使用了很多来编写包C++,因此更大的数据用户可以在几秒钟内将合并症分配给一百万患者。希望这可以帮助。

于 2017-06-22T15:19:12.377 回答