对包含因子、NA 值和通配符的数据框进行子集化
Subsetting a data frame containing factors, NA values, and wildcards
所以我有一个包含几个不同类别的大数据框,下面是一个简化的示例(真实数据集有 10 多种不同的组织,15 种以上不同的独特细胞类型,每个组织的名称长度可变,以及数千个基因)。组织列的格式为因子。
GENENAME Tissue1 Tissue2 Tissue3
Gene1 CellType_AA CellType_BB CellType_G
Gene2 CellType_AA CellType_BB <NA>
Gene3 CellType_AA <NA> <NA>
Gene4 CellType_AA CellType_BB CellType_G
Gene5 <NA> <NA> CellType_G
Gene6 <NA> CellType_BB CellType_H
Gene7 CellType_AC CellType_BD CellType_H
Gene8 <NA> <NA> CellType_H
Gene9 CellType_AC CellType_BD <NA>
Gene10 <NA> CellType_BB <NA>
Gene11 <NA> CellType_BD CellType_H
Gene12 CellType_AC <NA> <NA>
Gene13 <NA> CellType_E CellType_I
Gene14 CellType_F CellType_E CellType_I
Gene15 CellType_F CellType_E <NA>
我想做的是 return 基于多个组织中存在的 CellTypes 的子集,并在我这样做时忽略不必要的列。此外,我想使用通配符(在下面的示例中,CellType_A*
,以便同时选择 CellType_AA
和 CellType_AB
),并在我仅指定一些时忽略其他列列。我希望该函数可以轻松地重复用于不同的细胞类型组合,因此为每一列添加了一个单独的变量。
为此,我设置了下面的函数,将每个变量的默认值设置为 "*"
,认为如果我不指定输入,它会将这些列中的任何一个视为有效。
Find_CoEnrich <- function(T1="*", T2="*", T3="*"){
subset(dataset,
grepl(T1, dataset$Tissue1)
&grepl(T2, dataset$Tissue2)
&grepl(T3, dataset$Tissue3)
,select = GENENAME
)
}
但是当我运行函数只在一个列上时,要测试它
Find_CoEnrich(T1="CellType_AA")
它只会return以下内容:
GENENAME
1 Gene1
4 Gene4
而不是
1 Gene1
2 Gene2
3 Gene3
4 Gene4
跳过在另一列中包含 NA
的任何行。更神秘的是,如果我尝试使用通配符,它似乎会忽略字符串的其余部分,而只是 returns 只有那些在每一行中都有值的行,即使它们与字符串的其余部分不匹配,例如 Gene14
:
Find_CoEnrich(T1="CellType_A*")
GENENAME
1 Gene1
4 Gene4
7 Gene7
14 Gene14
我很确定是 table 中 NA
的存在导致了问题,但我花了很长时间试图纠正这个问题并且 运行 失去耐心。如果有人能提供帮助,将不胜感激。
您打算使用的通配符 *
作为正则表达式具有特定含义,这就是您告诉 grepl
接受哪些值的方式 - 它意味着前面的 0 次或多次重复特点。另外,我相信您需要在 grepl
表达式之间进行布尔 OR
(|
) 运算,因为您需要其中一列与模式匹配的任何行。
这里有一个可能更简单的解决方案,使用 tidyverse
,使用单独的 'row-based filtering' 和 'column selection' 步骤:
library(tidyverse)
dataset <- # small subset of your data, rows 1-4 should match but not 5
tribble(
~GENENAME, ~Tissue1, ~Tissue2, ~Tissue3,
"Gene1", "CellType_AA", "CellType_BB", "CellType_G",
"Gene2", "CellType_AA", "CellType_BB", NA,
"Gene3", "CellType_AA", NA, NA,
"Gene4", "CellType_AA", "CellType_BB", "CellType_G",
"Gene5", NA, NA, "CellType_G"
)
desired_pattern <- "CellType_A" # note that this already implies that any other character can follow, e.g. this will match CellType_AA, CellType_AB, etc.
dataset %>%
select(all_of(c("GENENAME","Tissue1","Tissue2","Tissue3"))) %>% # the column selection
filter(if_any( # this is a tad confusing: return the row if any of the specified columns matches the condition...
.cols = all_of(c("Tissue1", "Tissue2", "Tissue3")), # specify which columns to check
.fns = ~ stringr::str_detect(.x, pattern = desired_pattern) # specify the condition...str_detect() is basically grepl() under the hood
))
要更改为匹配的以 A 或 B 开头的单元格类型,您可以相应地更改模式:
desired_pattern <- "" # this will match any cell type that starts with A or B
编辑:
要查找同时匹配其中一列 CellType_A
和另一列 CellType_B
的行,您可以执行两个连续的过滤步骤:
dataset %>%
select(all_of(c("GENENAME","Tissue1","Tissue2","Tissue3"))) %>% # the column selection
filter(if_any( # in this step, keep only rows that contain at least one `CellType_A`
.cols = all_of(c("Tissue1", "Tissue2", "Tissue3")), # specify which columns to check
.fns = ~ stringr::str_detect(.x, pattern = "CellType_A")
)) %>%
filter(if_any( # in this step, keep only rows that contain at least one `CellType_B`
.cols = all_of(c("Tissue1", "Tissue2", "Tissue3")), # specify which columns to check
.fns = ~ stringr::str_detect(.x, pattern = "CellType_B")
))
以上两个过滤步骤的顺序无关紧要(您可以尝试调换顺序说服自己!)
所以我有一个包含几个不同类别的大数据框,下面是一个简化的示例(真实数据集有 10 多种不同的组织,15 种以上不同的独特细胞类型,每个组织的名称长度可变,以及数千个基因)。组织列的格式为因子。
GENENAME Tissue1 Tissue2 Tissue3
Gene1 CellType_AA CellType_BB CellType_G
Gene2 CellType_AA CellType_BB <NA>
Gene3 CellType_AA <NA> <NA>
Gene4 CellType_AA CellType_BB CellType_G
Gene5 <NA> <NA> CellType_G
Gene6 <NA> CellType_BB CellType_H
Gene7 CellType_AC CellType_BD CellType_H
Gene8 <NA> <NA> CellType_H
Gene9 CellType_AC CellType_BD <NA>
Gene10 <NA> CellType_BB <NA>
Gene11 <NA> CellType_BD CellType_H
Gene12 CellType_AC <NA> <NA>
Gene13 <NA> CellType_E CellType_I
Gene14 CellType_F CellType_E CellType_I
Gene15 CellType_F CellType_E <NA>
我想做的是 return 基于多个组织中存在的 CellTypes 的子集,并在我这样做时忽略不必要的列。此外,我想使用通配符(在下面的示例中,CellType_A*
,以便同时选择 CellType_AA
和 CellType_AB
),并在我仅指定一些时忽略其他列列。我希望该函数可以轻松地重复用于不同的细胞类型组合,因此为每一列添加了一个单独的变量。
为此,我设置了下面的函数,将每个变量的默认值设置为 "*"
,认为如果我不指定输入,它会将这些列中的任何一个视为有效。
Find_CoEnrich <- function(T1="*", T2="*", T3="*"){
subset(dataset,
grepl(T1, dataset$Tissue1)
&grepl(T2, dataset$Tissue2)
&grepl(T3, dataset$Tissue3)
,select = GENENAME
)
}
但是当我运行函数只在一个列上时,要测试它
Find_CoEnrich(T1="CellType_AA")
它只会return以下内容:
GENENAME
1 Gene1
4 Gene4
而不是
1 Gene1
2 Gene2
3 Gene3
4 Gene4
跳过在另一列中包含 NA
的任何行。更神秘的是,如果我尝试使用通配符,它似乎会忽略字符串的其余部分,而只是 returns 只有那些在每一行中都有值的行,即使它们与字符串的其余部分不匹配,例如 Gene14
:
Find_CoEnrich(T1="CellType_A*")
GENENAME
1 Gene1
4 Gene4
7 Gene7
14 Gene14
我很确定是 table 中 NA
的存在导致了问题,但我花了很长时间试图纠正这个问题并且 运行 失去耐心。如果有人能提供帮助,将不胜感激。
您打算使用的通配符 *
作为正则表达式具有特定含义,这就是您告诉 grepl
接受哪些值的方式 - 它意味着前面的 0 次或多次重复特点。另外,我相信您需要在 grepl
表达式之间进行布尔 OR
(|
) 运算,因为您需要其中一列与模式匹配的任何行。
这里有一个可能更简单的解决方案,使用 tidyverse
,使用单独的 'row-based filtering' 和 'column selection' 步骤:
library(tidyverse)
dataset <- # small subset of your data, rows 1-4 should match but not 5
tribble(
~GENENAME, ~Tissue1, ~Tissue2, ~Tissue3,
"Gene1", "CellType_AA", "CellType_BB", "CellType_G",
"Gene2", "CellType_AA", "CellType_BB", NA,
"Gene3", "CellType_AA", NA, NA,
"Gene4", "CellType_AA", "CellType_BB", "CellType_G",
"Gene5", NA, NA, "CellType_G"
)
desired_pattern <- "CellType_A" # note that this already implies that any other character can follow, e.g. this will match CellType_AA, CellType_AB, etc.
dataset %>%
select(all_of(c("GENENAME","Tissue1","Tissue2","Tissue3"))) %>% # the column selection
filter(if_any( # this is a tad confusing: return the row if any of the specified columns matches the condition...
.cols = all_of(c("Tissue1", "Tissue2", "Tissue3")), # specify which columns to check
.fns = ~ stringr::str_detect(.x, pattern = desired_pattern) # specify the condition...str_detect() is basically grepl() under the hood
))
要更改为匹配的以 A 或 B 开头的单元格类型,您可以相应地更改模式:
desired_pattern <- "" # this will match any cell type that starts with A or B
编辑:
要查找同时匹配其中一列 CellType_A
和另一列 CellType_B
的行,您可以执行两个连续的过滤步骤:
dataset %>%
select(all_of(c("GENENAME","Tissue1","Tissue2","Tissue3"))) %>% # the column selection
filter(if_any( # in this step, keep only rows that contain at least one `CellType_A`
.cols = all_of(c("Tissue1", "Tissue2", "Tissue3")), # specify which columns to check
.fns = ~ stringr::str_detect(.x, pattern = "CellType_A")
)) %>%
filter(if_any( # in this step, keep only rows that contain at least one `CellType_B`
.cols = all_of(c("Tissue1", "Tissue2", "Tissue3")), # specify which columns to check
.fns = ~ stringr::str_detect(.x, pattern = "CellType_B")
))
以上两个过滤步骤的顺序无关紧要(您可以尝试调换顺序说服自己!)