数据帧上下文中的模式匹配

时间:2011-10-27 03:50:19

标签: r pattern-matching dataframe

我有一个数据框,前5行看起来如下:

Sample    CCT6        GAT1                   IMD3          PDR3          RIM15
001       0000000000  111111111111111111111  010001000011  0N100111NNNN  01111111111NNNNNN
002       1111111111  111111111111111111000  000000000000  0N100111NNNN  00000000000000000
003       0NNNN00000  000000000000000000000  010001000011  000000000000  11111111111111111
004       000000NNN0  11100111111N111111111  010001000011  111111111111  01111111111000000
005       0111100000  111111111111111111111  111111111111  0N100111NNNN  00000000000000000

完整数据集有2000个样本。我正在尝试编写代码,让我可以判断5列中每列的数字串是否在我的所有样本中都是同质的(即全部为1或0)。理想情况下,我还希望能够在答案为True的情况下区分1和0。从我的例子来看,预期结果将是:

Sample    CCT6        GAT1         IMD3          PDR3          RIM15
001       TRUE (0)    TRUE (1)     FALSE         FALSE         FALSE
002       TRUE (1)    FALSE        TRUE (0)      FALSE         TRUE (0)
003       FALSE       TRUE (0)     FALSE         TRUE (0)      TRUE (1)
004       FALSE       FALSE        FALSE         TRUE (1)      FALSE
005       FALSE       TRUE (1)     TRUE (1)      FALSE         TRUE (0)

我没有坚持使用逻辑,我可以使用字符,只要它们可以用来区分不同的类。理想情况下,id喜欢在类似的数据框中返回结果。

我遇到了最基本的第一步问题,就是让R告诉字符串是否包含所有相同的值。我已尝试使用grepregexpr使用各种表达式,但无法获得可用于使用ddply或类似内容应用整个数据框的结果。以下是我为此步骤尝试过的一些示例:

a = as.character("111111111111")
b = as.character("000000000000")
c = as.character("000000011110")


> grep("1",a)
[1] 1

> grep("1",c)
[1] 1

> regexpr("1",a)
[1] 1
attr(,"match.length")
[1] 1
> regexpr("1",c)
[1] 8
attr(,"match.length")
[1] 1

我非常感谢帮助我解决这个问题,或者帮助我实现更大的目标。

3 个答案:

答案 0 :(得分:5)

这是一个REGEX表达式,它将匹配带有一个或多个字符的零或1:

(^[0]+$)|(^[1]+$)

以下将匹配: 0000 0 111111 11 1

这不匹配: 000001

答案 1 :(得分:4)

这是一个完整的解决方案。可能是矫枉过正,但也很有趣。

关键位是markTRUE功能。它使用反向引用(\\1)来引用先前由第一个带括号的子表达式匹配的子字符串(01)。

正则表达式"^(0|1)(\\1)+$"表示'匹配任何以01开头的字符串,然后跟随(直到字符串结尾)重复1次或更多次同样的人物 - 无论是什么'。在同一次gsub()调用中,我使用相同的反向引用来替换"TRUE (0)""TRUE (1)"

首先阅读数据:

dat <- 
read.table(textConnection("
Sample     CCT6        GAT1                   IMD3           PDR3          RIM15
001       0000000000  111111111111111111111  010001000011  0N100111NNNN  01111111111NNNNNN
002       1111111111  111111111111111111000  000000000000  0N100111NNNN  00000000000000000
003       0NNNN00000  000000000000000000000  010001000011  000000000000  11111111111111111
004       000000NNN0  11100111111N111111111  010001000011  111111111111  01111111111000000
005       0111100000  111111111111111111111  111111111111  0N100111NNNN  00000000000000000"),
header=T)

然后释放正则表达式:

markTRUE <- function(X) {
    gsub(X, pattern = "^(0|1)(\\1)+$", 
         replacement = "TRUE (\\1)")
}

markFALSE <- function(X) {
    X[!grepl("TRUE", X)]  <- "FALSE"
    return(X)
}

dat[-1] <- lapply(dat[-1], markTRUE)
dat[-1] <- lapply(dat[-1], markFALSE)

dat
#   Sample     CCT6     GAT1     IMD3     PDR3    RIM15
# 1      1 TRUE (0) TRUE (1)    FALSE    FALSE    FALSE
# 2      2 TRUE (1)    FALSE    FALSE    FALSE TRUE (0)
# 3      3    FALSE TRUE (0)    FALSE TRUE (0) TRUE (1)
# 4      4    FALSE    FALSE    FALSE TRUE (1)    FALSE
# 5      5    FALSE TRUE (1) TRUE (1)    FALSE TRUE (0)

答案 2 :(得分:2)

一种可能的方法是使用strsplitunique

> unique(unlist(strsplit("111111111122","")))
[1] "1" "2"

然后检查结果是否为长度为1,如果是,则检查结果是“1”还是“0”。