R中大型数据集中多个列的自动grep()

Posted

技术标签:

【中文标题】R中大型数据集中多个列的自动grep()【英文标题】:Automated grep() across multiple columns in large dataset in R 【发布时间】:2016-08-13 19:35:42 【问题描述】:

编辑底部的可重现示例...

我正在处理一个大型数据集(来自 CDC 的汇集 NHAMCS):

> dim(ed0509) [1] 174020 514

我在使用 grep() 根据多列变量 DIAG1 DIAG2 DIAG3 基于感兴趣的向量列表 SSTI.list 中的模式识别数据框中的行时遇到问题。条件是,如果在任一列变量中识别出此模式,那么我想提取该行号以最终使用它来对数据进行子集化以在数据集中创建一个新的分类列SSTI.cat(0 或 1) .

SSTI.list <- c("035", "566", "60883", "6110", "6752", "6751", "680","681","682","683","684","684","685","686", "7048", "70583","7070", "7078", "7079", "7071", "7280", "72886", "7714", "7715", "7854", "9583", "99662", "99762", "9985")

由于我要处理的元素列表很长,超过 1000 个,因此我正在尝试使用 for 循环自动执行此过程。所需的输出是具有包含向量SSTI.list 中每个值的行列表的新变量。我主要在 grep() 中运行 for 循环时遇到问题,我收到错误:

argument 'pattern' has length > 1 and only the first element will be used

到目前为止,我尝试做的是:

diags <- c(ed0509$DIAG1,ed0509$DIAG2,ed0509$DIAG3)

for (i in SSTI.list) assign(paste("var",i,sep=""),grep(paste("^",i,"",sep=""),diags,value=F))

SSTI.comb 将是最终的行列表(所有 vari),从用于创建分类变量 SSTI.cat 的 for 循环中识别出 SSTI.list 中的模式

然后使用data.table 包创建分类变量。

SSTI.comb<-sort(as.numeric(SSTI.comb))

setDT(ed0509)[SSTI.comb,SSTI.cat:=1][,SSTI.cat:=0]

编辑为了重现性,对此感到抱歉...

DIAG1=c("00000","4659-","0356-","5664-","771--","7715-","78791")
DIAG2=c("3829-","00000","00000","4659-","7854-","00000","566--")
DIAG3=c("9985-","00000","00000","00000","00000","00000","00000")
df<-data.frame(DIAG1,DIAG2,DIAG3)`

SSTI.list <- c("035","9985","7854","771","7715")

for (i in SSTI.list)
assign(paste("var",i,sep=""),grep(paste("^",i,"",sep=""),diags,value=F))

从概念上讲,我希望有一个输出,其中附加到df 的新列变量将指示第 1、第 3、第 5 和第 6 行被识别为满足SSTI.list 中指示的模式

DIAG1 DIAG2 DIAG3 SSTI.cat
1 00000 3829- 9985-        1
2 4659- 00000 00000        0
3 0356- 00000 00000        1
4 5664- 4659- 00000        0
5 771-- 7854- 00000        1
6 7715- 00000 00000        1
7 78791 566-- 00000        0

【问题讨论】:

您能否通过添加数据集和预期输出数据集的示例来提出问题reproducible? 您是否需要SSTI.list 中的元素与数据中的元素完全匹配,或者它是否只有匹配部分值。例如,如果数据中的一个元素是"683035",那么这是否应该导致与来自SSTI.list"035" 匹配,还是应该只匹配数据中的“035”与SSTI.list 中的“035”? @thepule 我添加了一个可重现的示例和所需的输出。 @eipi10 我在grep() 中使用了^ 来表示我希望元素基于字符串的开头,因此SSTI.list 中的"035" 将识别"0351-""03568",但不是"683035" . 【参考方案1】:

这是我在您添加数据之前制作的虚假数据示例。如果这是您的想法,请告诉我:

SSTI.list <- c("035", "566", "60883", "6110", "6752", "6751", "680","681","682","683","684","684",
               "685","686", "7048", "70583","7070", "7078", "7079", "7071", "7280", "72886", 
               "7714", "7715", "7854", "9583", "99662", "99762", "9985")

# Fake data
set.seed(10)
dat = as.data.frame(replicate(5, sample(c(SSTI.list, 1e5:(1e5+1000)),10)), stringsAsFactors=FALSE)
       V1     V2     V3     V4     V5
1  100493 100642 100861 100522 100254
2  100286 100555 100604 100066 100206
3  100409 100087 100767 100145   7048
4  100682 100583 100336 100895 100719
5  100058 100338 100387 100404 100227
6  100202 100410 100695 100737 100136
7  100252 100024 100829 100813   7078
8  100249 100241 100216 100947 100468
9  100600 100378 100758 100671 100076
10 100998 100824 100334 100482 100789
# Match any instance of a pattern within any element of the data
dat[apply(dat, 1, function(i) any(grepl(paste(SSTI.list, collapse="|"), i))),]
      V1     V2     V3     V4     V5
3 100409 100087 100767 100145   7048
4 100682 100583 100336 100895 100719  # "100682 matches "682" in SSTI.list
7 100252 100024 100829 100813   7078
# Match only if a data element is exactly the same as one of the patterns.
dat[apply(dat, 1, function(i) any(grepl(paste(paste0("^",SSTI.list,"$"), collapse="|"), i))),]
      V1     V2     V3     V4   V5
3 100409 100087 100767 100145 7048
7 100252 100024 100829 100813 7078

如果你只想要匹配行的行索引:

which(apply(dat, 1, function(i) any(grepl(paste(SSTI.list, collapse="|"), i))))

[1] 3 4 7

【讨论】:

是的,这就是我想要的!我是 R 编程新手,非常感谢您对此提供的帮助。我想知道这是否是唯一的方法,或者是否有任何现有的软件包可以做到这一点? 在 R 中几乎总是有多种方法可以做事,如果我的答案是最有效的,我会感到惊讶。 stringrstringidata.table 包可能更简单和/或更快,并且在基本 R 中也可能有更好的方法。希望有人会提出其他选择。 有趣,我会研究一下那些包。我还有一个问题,是否可以将apply() 中的dat 替换为标识dat 中特定列的向量,换句话说,如果我只想考虑DIAG1DIAG3?或者只是DIAG2 然后执行dat[ , c("DIAG1", "DIAG3", "DIAG5")]。或者,更简洁地说,dat[ , paste0("DIAG", c(1,3,5)]。或者,dat[ , grep("1|3|5", names(dat))](请注意,后者也将匹配“DIAG11”或“DIAG35”,因此您必须小心您的模式)。就像我说的,在 R 中做事的方法很多!

以上是关于R中大型数据集中多个列的自动grep()的主要内容,如果未能解决你的问题,请参考以下文章

R:从R中的大型数据集中根据列中的值删除行[重复]

从子集中选择观察值以基于 R 中的大型数据框创建新子集

使用 Spark 过滤大型数据集中的列

R语言vtreat包自动处理dataframe的缺失值并生成对应的数据列_isbad来指示数据的原始缺失情况查看特定字段缺失的那些数据行查看数据集中多个字段的均值

查找大型数据集中的两个日期之间是不是有假期?

通过 SQL 或 R 对大型数据集进行有效分析? [关闭]