R 在一个单元格内选择最小值或最大值(分隔字符串)
我有一个数据框,其中每个样本的列可以有多个值,例如:R 在一个单元格内选择最小值或最大值(分隔字符串),r,dataframe,max,min,data.table,matrixstats,R,Dataframe,Max,Min,Data.table,Matrixstats,我有一个数据框,其中每个样本的列可以有多个值,例如: Gene Pvalue1 Pvalue2 Pvalue3 Beta Ace 0.0381, ., 0.00357 0.01755, 0.001385 0.0037, NA , 0.039 -0.03,1,15 NOS NA 0.02 0.
Gene Pvalue1 Pvalue2 Pvalue3 Beta
Ace 0.0381, ., 0.00357 0.01755, 0.001385 0.0037, NA , 0.039 -0.03,1,15
NOS NA 0.02 0.001, 0.00067 0.00009,25,30
我想对每列中每个基因的数据(我总共有数千个基因)应用min()
和max()
,并获得pvalues的最小值,但beta等列的最大值。因此,输出数据如下所示:
Gene Pvalue1 Pvalue2 Pvalue3 Beta
Ace 0.00357 0.001385 0.0037 15
NOS NA 0.02 0.00067 30
我是R新手,不确定我所问的是否可行,如果一个单元格中有多个值,它们是否被视为字符串?使用
stringr
和dplyr
的可能解决方案:
library(dplyr)
library(stringr)
getmin = function(col) str_extract_all(col,"[0-9\\.-]+") %>%
lapply(.,function(x) min(as.numeric(x),na.rm = T) ) %>%
unlist()
df %>%
mutate_at(names(df)[-1],getmin)
Gene Pvalue1 Pvalue2 Pvalue3 Beta
1 Ace 0.00357 0.001385 0.00370 -3e-02
2 NOS Inf 0.020000 0.00067 9e-05
Warning messages:
1: In FUN(X[[i]], ...) : NAs introduced by coercion
2: In min(as.numeric(x), na.rm = T) :
no non-missing arguments to min; returning Inf
函数getmin
使用str\u extract\u all
提取数字:
str_extract_all(df$Pvalue2,"[0-9\\.-]+")
[[1]]
[1] "0.01755" "0.001385"
[[2]]
[1] "0.02"
它的优点是对空格或其他字符不敏感,但只能提取一个点。然后我在这个列表上循环,以提取每个单元格中的最小值,并将列表转换为一个带有unlist
的向量。使用as.numeric()
函数将可能提取的
转换为NA
代码df%>%mutate_at(names(df)[-1],getmin)
只需在除第一列之外的所有列上应用此函数
编辑:如果要避免inf值,可以使用此稍加修改的版本:
min2 = function(x) if(all(is.na(x))) NA else min(x,na.rm = T)
getmin = function(col) str_extract_all(col,"[0-9\\.-]+") %>%
lapply(.,function(x)min2(as.numeric(x)) ) %>%
unlist()
df %>%
mutate_at(names(df)[-1],getmin)
Gene Pvalue1 Pvalue2 Pvalue3 Beta
1 Ace 0.00357 0.001385 0.00370 -3e-02
2 NOS NA 0.020000 0.00067 9e-05
数据:
df这里是总体思路
applyFunctionToString <- function(
string
, sep = ","
){
string <- gsub(" ", "", string)
string <- unlist(strsplit(string, sep))
string[string == "NA"] <- NA
numbers <- as.numeric(string)
min(numbers, na.rm = TRUE)
}
sapply(c("0.01755, 0.001385", "0.0037, NA , 0.039"), applyFunctionToString)
applyFunctionToString这里是一个基本的R解决方案,使用regmatches
+gregexpr
来排序数字,即
dPvalue <- t(apply(df[grep("Pvalue",names(df))], 1, function(v) {
unlist(Map(function(x) ifelse(length(x)>0, min(as.numeric(x)),NA), regmatches(v, gregexpr("-?\\d+(\\.\\d+)?",v))))
}))
Beta <- apply(df[grep("Beta",names(df))], 1, function(v) {
unlist(Map(function(x) ifelse(length(x)>0, max(as.numeric(x)),NA), regmatches(v, gregexpr("-?\\d+(\\.\\d+)?",v))))
})
dfout <- cbind(df["Gene"],Pvalue,Beta)
数据
df <- structure(list(Gene = structure(1:2, .Label = c("Ace", "NOS"), class = "factor"),
Pvalue1 = structure(c(1L, NA), .Label = "0.0381,.,0.00357", class = "factor"),
Pvalue2 = structure(1:2, .Label = c("0.01755,0.001385", "0.02"
), class = "factor"), Pvalue3 = structure(2:1, .Label = c("0.001,0.00067",
"0.0037,NA,0.039"), class = "factor"), Beta = structure(1:2, .Label = c("-0.03,1,15",
"0.00009,25,30"), class = "factor")), class = "data.frame", row.names = c(NA,
-2L))
df使用data.table,将宽转换为长,用逗号分割,得到p值的最小值和beta值的最大值,最后转换回长转换为宽
library(data.table)
dt1 <- fread("
Gene Pvalue1 Pvalue2 Pvalue3 Beta
Ace 0.0381,.,0.00357 0.01755,0.001385 0.0037,NA,0.039 -0.03,1,15
NOS NA 0.02 0.001,0.00067 0.00009,25,30
")
dcast(
melt(dt1, id.vars = "Gene")[, paste0("col", 1:3) := lapply(tstrsplit(value, ","), as.numeric)
][, MinMax := ifelse(grepl("Pvalue", variable),
pmin(col1, col2, col3, na.rm = TRUE),
pmax(col1, col2, col3, na.rm = TRUE)) ],
Gene ~ variable, value.var = "MinMax")
# Gene Pvalue1 Pvalue2 Pvalue3 Beta
# 1: Ace 0.00357 0.001385 0.00370 15
# 2: NOS NA 0.020000 0.00067 30
# Warning message:
# In lapply(tstrsplit(value, ","), as.numeric) : NAs introduced by coercion
库(data.table)
dt1另一个选项是使用和:
对于Beta
-列,您可以创建一个类似的max_-fun
:只需将rowMins
替换为rowMaxs
,您好!如果你能提供一个可以直接放入R中的样本,这会更容易。你的问题“它们是否被视为字符串”可以用这种方式得到最简单的回答,但我认为它们确实是一个字符串。因此,我会尝试使用apply函数,将函数的组合放在如下位置:(对于最小值)min(str_split())。您好,谢谢。我将立即研究apply函数和您建议的函数组合。我如何提供直接进入R的样品?抱歉,如果这是一个基本问题,那么这听起来非常有用。使用类似dput()的内容将给出结构/数据,前几行通常足以回答这样的问题(可以使用head()函数)这是可能的(有时非常有用)要在一个单元格中包含多个数值,您应该测试str_extract
和str_extract
中的str_all
函数,这允许您自制函数的大部分功能感谢您,这几乎可以正常工作,但出于某种原因,它将我的负数值定为正数(因此选择了错误的最小值/最大值)。这是我最了解的解释,因此我将继续努力,看看是否可以解决此问题,谢谢您的帮助!我一直在尝试解决此问题,似乎我需要修改“[0-9\\\.]+”
以某种方式解释负数,但我没有发现任何类似的问题。如果您知道此问题的解决方案,请告诉我。很抱歉,我没有看到负数。您可以使用[0-9\\.-]
取而代之的是,请看我的编辑。谢谢你。这几乎可以工作,但会产生6000多个变量,你知道这是为什么吗?我会继续研究解决这个问题,因为除了代码运行之外。@DN1如果你想在全局环境中保持干净并且变量更少,你可以编写自定义函数来包装所有变量我有6000多个基因,它给了我想要的列的最小值和最大值,但它转换了结果,所以每个基因的pValue本身就变成了一行。我会研究转置这个,再次感谢你的帮助
df <- structure(list(Gene = structure(1:2, .Label = c("Ace", "NOS"), class = "factor"),
Pvalue1 = structure(c(1L, NA), .Label = "0.0381,.,0.00357", class = "factor"),
Pvalue2 = structure(1:2, .Label = c("0.01755,0.001385", "0.02"
), class = "factor"), Pvalue3 = structure(2:1, .Label = c("0.001,0.00067",
"0.0037,NA,0.039"), class = "factor"), Beta = structure(1:2, .Label = c("-0.03,1,15",
"0.00009,25,30"), class = "factor")), class = "data.frame", row.names = c(NA,
-2L))
library(data.table)
dt1 <- fread("
Gene Pvalue1 Pvalue2 Pvalue3 Beta
Ace 0.0381,.,0.00357 0.01755,0.001385 0.0037,NA,0.039 -0.03,1,15
NOS NA 0.02 0.001,0.00067 0.00009,25,30
")
dcast(
melt(dt1, id.vars = "Gene")[, paste0("col", 1:3) := lapply(tstrsplit(value, ","), as.numeric)
][, MinMax := ifelse(grepl("Pvalue", variable),
pmin(col1, col2, col3, na.rm = TRUE),
pmax(col1, col2, col3, na.rm = TRUE)) ],
Gene ~ variable, value.var = "MinMax")
# Gene Pvalue1 Pvalue2 Pvalue3 Beta
# 1: Ace 0.00357 0.001385 0.00370 15
# 2: NOS NA 0.020000 0.00067 30
# Warning message:
# In lapply(tstrsplit(value, ","), as.numeric) : NAs introduced by coercion
library(data.table)
library(matrixStats)
pval_cols <- grep("Pvalue", names(DT), fixed = TRUE, value = TRUE)
min_fun <- function(x) {
y <- tstrsplit(x, split = ",", fixed = TRUE)
y <- rowMins(sapply(y, as.numeric), na.rm = TRUE)
y <- replace(y, !is.finite(y), NA)
return(y)
}
DT[, (pval_cols) := lapply(.SD, min_fun)
, .SDcols = pval_cols][]
> DT
Gene Pvalue1 Pvalue2 Pvalue3 Beta
1: Ace 0.00357 0.001385 0.00370 -0.03,1,15
2: NOS NA 0.020000 0.00067 0.00009,25,30