【问题标题】:How to select max numeric value out of numeric characters?如何从数字字符中选择最大数值?
【发布时间】:2020-12-04 11:56:21
【问题描述】:

我有一个按Gene 列分组的数据集。分组到每一行的一些值只是.,,所以我删除了它们,每行和每列只留下几个数字字符。

要做到这一点是编码:

#Group by Gene:
data <- setDT(df2)[, lapply(.SD, paste, collapse = ", "), by = Genes]

#Remove ., from anywhere in the dataframe
dat <- data.frame(lapply(data, function(x) {
  gsub("\\.,|\\.$|\\,$|(, .$)", "", x)
}))

我在删除., 之前和按Gene 分组之后的数据如下所示:

Gene    col1                     col2                  col3           col4
ACE     0.3, 0.4, 0.5, 0.5       .                      ., ., .        1, 1, 1, 1, 1
NOS2    ., .                     .                      ., ., ., .     0, 0, 0, 0, 0
BRCA1   .                                               ., .           1, 1, 1, 1, 1
HER2    .                        0.1, ., .,  0.2, 0.1   .              1, 1, 1, 1, 1

删除., 后,我的数据如下所示:

Gene    col1                 col2               col3     col4
ACE     0.3, 0.4, 0.5, 0.5                               1, 1, 1, 1, 1
NOS2                                                     0, 0, 0, 0, 0
BRCA1                                                    1, 1, 1, 1, 1
HER2                         0.1,      0.2, 0.1          1, 1, 1, 1, 1

我现在正在尝试选择每行和每列的最小值或最大值。

期望示例输出:

Gene    col1                 col2            col3    col4
ACE     0.5                                           1
NOS2                                                  0
BRCA1                                                 1
HER2                          0.1                     1

#For col1 I need the max value per row (so for ACE 0.5 is selected)
#For col2 I need the min value per row

请注意,我的实际数据是 100 列和 20,000 行 - 不同的列需要每个选定基因的最大值或最小值。

但是,使用我使用的代码,我只获得了col4 的预期输出,而我的其他列重复了两次选定的值(我得到了0.5, 0.50.1, 0.1,我不知道为什么)。

我用来选择最小值/最大值的代码是:

#Max value per feature and row
max2 = function(x) if(all(is.na(x))) NA else max(x,na.rm = T)
getmax = function(col) str_extract_all(col,"[0-9\\.-]+") %>%
  lapply(.,function(x)max2(as.numeric(x)) ) %>%
  unlist() 

#Min value per feature and row
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() 

data <- dt %>%
  mutate_at(names(dt)[2],getmax)

data <- dt %>%
  mutate_at(names(dt)[3],getmin)

data <- dt %>%
  mutate_at(names(dt)[4],getmax)

为什么这些选择功能不适用于我的所有列?所有列都是字符类。我还想知道是否我什至需要删除 ., 并且可以直接跳转到选择每行和每列的最大值/最小值?

输入数据示例:

structure(list(Gene = c("ACE", "NOS2", "BRCA1", "HER2"), col1 = c("0.3, 0.4, 0.5, 0.5", 
"", "", ""), col2 = c("", "", "", "  0.1,      0.2 0.,1"), col3 = c(NA, 
NA, NA, NA), col4 = c("                         1, 1, 1, 1, 1", 
"                                     0, 0, 0, 0, 0", "                                     1, 1, 1, 1, 1", 
"     1, 1, 1, 1, 1")), row.names = c(NA, -4L), class = c("data.table", 
"data.frame"))

【问题讨论】:

  • 我不确定您的数据从哪里开始,但使用dt[, lapply(.SD, max), Gene] 可能更有效。由于您的数据似乎是一个字符,因此使用函数 function(x) max(as.numeric(x), na.rm = TRUE) 可能会有所帮助。基本上,尝试通过直接将函数应用于原始数据来查看是否可以跳过折叠后跟正则表达式。

标签: r dplyr data.table max min


【解决方案1】:

您可以使用type.convert 并将其参数na.strings 设置为"."。您可能还想使用range 函数一次性获得最小值和最大值。

假设您的 data.table 看起来像这样

> dt
    Gene               col1                 col2       col3          col4
1:   ACE 0.3, 0.4, 0.5, 0.5                    .    ., ., . 1, 1, 1, 1, 1
2:  NOS2               ., .                    . ., ., ., . 0, 0, 0, 0, 0
3: BRCA1                  .                            ., . 1, 1, 1, 1, 1
4:  HER2                  . 0.1, ., .,  0.2, 0.1          . 1, 1, 1, 1, 1

考虑这样的函数

library(data.table)
library(stringr)

get_range <- function(x) {
  x <- type.convert(str_split(x, ",\\s+", simplify = TRUE), na.strings = ".")
  x <- t(apply(x, 1L, function(i) {
    i <- i[!is.na(i)]
    if (length(i) < 1L) c(NA_real_, NA_real_) else range(i)
  }))
  dimnames(x)[[2L]] <- c("min", "max")
  x
}

那么你就可以了

dt[, c(Gene = .(Gene), lapply(.SD, get_range)), .SDcols = -"Gene"]

输出

    Gene col1.min col1.max col2.min col2.max col3.min col3.max col4.min col4.max
1:   ACE      0.3      0.5       NA       NA       NA       NA        1        1
2:  NOS2       NA       NA       NA       NA       NA       NA        0        0
3: BRCA1       NA       NA       NA       NA       NA       NA        1        1
4:  HER2       NA       NA      0.1      0.2       NA       NA        1        1

请注意,Gene 不需要这样做,因为函数 get_range 已经矢量化了。

【讨论】:

    猜你喜欢
    • 2013-05-06
    • 2015-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-14
    相关资源
    最近更新 更多