有多少人接受了 4 种感兴趣的药物? R

how many people received 4 drugs of interest? R

我有一长串接受变量 ATC 编码药物的人。我想知道有多少人使用过 4 种特定药物。例如,我想统计有多少人使用过这种特定模式的药物 "C07ABC" & "C09XYZ" &"C08123" &"C03ZOO"。有些人可能不止一次使用过某些药剂(例如 C07 或 C08),没关系,我只想数一数有多少独特的人拥有我感兴趣的方案。我不在乎他们有多少次独特的药物。但是,因为我想查找各种模式 - 我想使用 grepl 函数。为了进一步解释这一点,我第一次尝试解决这个问题时尝试了一个求和命令:

sum(df[grepl('^C07.*?'|'^C09.*?'|'^C08.*?|C03.*?', as.character(df$atc)),])

但是这不起作用,因为我认为 sum 命令需要一个布尔函数。另外,我认为这里的符号也不正确(我想要一个 &),但我只是展示代码,这样你就知道我在找什么了。也许我需要一个 ave 函数 - 但我不确定我将如何编写它?

提前致谢。

df
   names  fruit      dates     atc
4   john   kiwi 2010-07-01  C07ABC
7   john  apple 2010-09-01  C09XYZ
9   john banana 2010-11-01  C08123
13  john orange 2010-12-01  C03ZOO
14  john  apple 2011-01-01  C07ABC
2   mary orange 2010-05-01  C09123
5   mary  apple 2010-07-01  C03QRT
8   mary orange 2010-07-01  C09ZOO
10  mary  apple 2010-09-01  C03123
12  mary  apple 2010-11-01  C09123
1    tom  apple 2010-02-01  C03897
3    tom banana 2010-03-01 C02CAMN
6    tom  apple 2010-06-01  C07123
11   tom   kiwi 2010-08-01 C02DA12

您可以考虑避免使用正则表达式,而是从列 atc 派生出一些有意义的列集。对于组合,您可能需要人和药物的 2-way table,然后在矩阵上计算以计算组合。

例如:

tab <- xtabs(~ names + atc, df)
combo <- c("C07ABC", "C09XYZ", "C08123", "C03ZOO")
haveCombo <- rowSums(tab[,combo] > 0) == length(combo)
sum(haveCombo)

最后两行可以很容易地变成每个组合的函数。

编辑:此方法可应用于其他派生列,因此如果您对前缀感兴趣,

df$agent <- substring(df$atc, 1, 3)
tab <- xtabs(~ names + agent, df)
combo <- c("C07", "C09", "C08", "C03")  

像以前一样继续。

你可以试试这个

drugs <- c("C07ABC","C09XYZ", "C08123", "C03ZOO")
table(unique(df[df$atc %in% drugs, c("names", "atc")])$names)
# john mary  tom 
#   4    0    0 
names(which(table(unique(df[df$atc %in% drugs, c("names", "atc")])$names) > 3))
# [1] "john"

数据

df <- structure(list(names = structure(c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 
2L, 2L, 2L, 3L, 3L, 3L, 3L), .Label = c("john", "mary", "tom"
), class = "factor"), fruit = structure(c(3L, 1L, 2L, 4L, 1L, 
4L, 1L, 4L, 1L, 1L, 1L, 2L, 1L, 3L), .Label = c("apple", "banana", 
"kiwi", "orange"), class = "factor"), dates = structure(c(5L, 
7L, 8L, 9L, 10L, 3L, 5L, 5L, 7L, 8L, 1L, 2L, 4L, 6L), .Label = c("2010-02-01", 
"2010-03-01", "2010-05-01", "2010-06-01", "2010-07-01", "2010-08-01", 
"2010-09-01", "2010-11-01", "2010-12-01", "2011-01-01"), class = "factor"), 
    atc = structure(c(8L, 11L, 9L, 6L, 8L, 10L, 5L, 12L, 3L, 
    10L, 4L, 1L, 7L, 2L), .Label = c("C02CAMN", "C02DA12", "C03123", 
    "C03897", "C03QRT", "C03ZOO", "C07123", "C07ABC", "C08123", 
    "C09123", "C09XYZ", "C09ZOO"), class = "factor")), .Names = c("names", 
"fruit", "dates", "atc"), class = "data.frame", row.names = c("4", 
"7", "9", "13", "14", "2", "5", "8", "10", "12", "1", "3", "6", 
"11"))

除了不需要将整个数据帧行传送到 sum 之外,您还在该模式中添加了额外的引号:

> sum( grepl('^C07.*|^C09.*|^C08.*|C03.*', df$atc) )
[1] 12

我认为这样更容易阅读:

>  sum( grepl('^(C07|C09|C08|C03).*', df$atc) )
[1] 12

但现在我读到您想要使用所有这些并在患者 ID 内进行计算。这可能需要使用 & 作为连接器,但我决定尝试不同的路线并使用 unique,然后在 aggregate 操作中计算唯一匹配项的数量。

> aggregate(atc ~ names, data=df, 
                       function(drgs) length(unique(grep('^(C07|C09|C08|C03)', drgs))))
  names atc
1  john   5
2  mary   5
3   tom   2

虽然这是匹配项的数量而不是唯一项的数量,因为我忘记在 grep 调用中输入 value=TRUE (并且还需要使用 substr 来单独避免计算具有不同尾随 ATC 代码的同类物):

> aggregate(atc ~ names, data=df, function(drgs) length(unique(grep('^C0[7983]', substr(drgs,1,3), value=TRUE))))
  names atc
1  john   4
2  mary   2
3   tom   2

这有点类似于@MichaelLawrence 的matrix/table 方法,但我认为它会更好地扩展,因为创建的"tables" 会小得多:

 combo <- c("C07", "C09", "C08", "C03")
 tapply(df$atc, df$names, function(drgs) sum(combo %in% substr(drgs,1,3)) )
#------
john mary  tom 
   4    2    2 

这只是@Michael Lawrence 回答的延续。我将药物更改为 @user2363642 想要的,并且我还对 atc 列进行了子字符串化以仅使用前三个字符,我相信这也是 @user2363642 想要的。此外,对于 rowSums,我首先将所有非零数量更改为 1,以确保我们不会重复计算药物。

drugs <- c("C07", "C09", "C08", "C03")
df$atc.abbr <- substring(df$atc, 1, 3)

xt <- xtabs(~ names + atc.abbr, df)
xt[xt>0] <- 1
rowSums(xt[,drugs]) >= length(drugs) 

输出:

 john  mary   tom 
 TRUE FALSE FALSE