如何在注意数字以前是否为负数的同时获得绝对值?

How to get the absolute value while noting if the number used to be negative?

我有一个遗传数据集,其中每一行都描述了一个基因,并且有一个包含多个 beta 值的 beta 列,我已将其压缩为一个 row/cell(从一个基因中的多个变体给出多个 beta 的变体级别). Beta 是基因在某种情况下可能产生的效应大小,因此大的负值和大的正值都很重要。我正在尝试编写从行中选择绝对值的代码,然后尝试创建另一个新列来记录绝对值是否曾经是负数 - 我有生物学背景所以我不确定这是否可能或最好的方法是什么?

例如我的数据是这样的:

Gene    Beta
ACE     0.01, -0.6, 0.4
BRCA    0.7, -0.2, 0.2 
ZAP70   NA
P53     0.8, -0.6, 0.001

预期输出如下(选择绝对值并跟踪哪些数字曾经是负数):

Gene    Beta     Negatives
ACE      0.6         1
BRCA     0.7         0
ZAP70    NA          NA
P53      0.8         0

我目前坚持从每一行中获取绝对值,我正在尝试的是:

abs2 = function(x) if(all(is.na(x))) NA else abs(x,na.rm = T)
getabs = function(col) str_extract_all(col,"[0-9\.-]+") %>%
  lapply(.,function(x)abs2(as.numeric(x)) ) %>%
  unlist() 

test <- df %>%
  mutate_at(names(df)[2],getabs)

#Outputs:
 Error in abs(x, na.rm = T) : 2 arguments passed to 'abs' which requires 1 

任何关于如何获得每个 cell/row 的绝对值的帮助将不胜感激,因为我假设我也可以使列获得最大的负值,将其与相同的绝对值匹配并将其用作我的底片记录。

输入数据:

dput(df)
structure(list(Gene = c("ACE", "BRCA", "ZAP70", "P53"), `Beta` = c("0.01, -0.6, 0.4", 
"0.7, -0.2, 0.2", "0.001, 0.02, -0.003", "0.8, -0.6, 0.001")), row.names = c(NA, 
-4L), class = c("data.table", "data.frame"))

你可以简单地拆分,转换成数字,找到绝对最大值的索引并检查它是否为负数,即

sapply(strsplit(df$Beta, ', '), function(i){i1 <- as.numeric(i); 
                                            i2 <- which.max(abs(i1));
                                         if (length(i2) == 0){NA}else{i[i2] < 0}}) * 1

#[1]  1  0 NA  0

使用 dplyr 的一种方法是将逗号分隔值放入单独的行中,group_by Gene 获取 Betamax 绝对值并检查该值是否为负数。

library(dplyr)

df %>%
  tidyr::separate_rows(Beta, sep = ",", convert = TRUE) %>%
  group_by(Gene) %>%
  summarise(Negatives = +(min(Beta) == -max(abs(Beta))),
            Beta = max(abs(Beta), na.rm = TRUE))

# A tibble: 4 x 3
#  Gene  Negatives   Beta
#  <fct>     <int>  <dbl>
#1 ACE           1    0.6
#2 BRCA          0    0.7
#3 P53           0    0.8
#4 ZAP70        NA   -Inf  

数据

df <- structure(list(Gene = structure(c(1L, 2L, 4L, 3L), .Label = c("ACE", 
"BRCA", "P53", "ZAP70"), class = "factor"), Beta = structure(c(1L, 
2L, NA, 3L), .Label = c("0.01, -0.6, 0.4", "0.7, -0.2, 0.2", 
"0.8, -0.6, 0.001"), class = "factor")), class = "data.frame", 
row.names = c(NA, -4L))

您可以编写自定义函数 f 并通过 Vectorize 对其进行矢量化,即

f <- Vectorize(function(x) {
  v <- as.numeric(unlist(strsplit(as.character(x),split = ",")))
  c(Beta = max(abs(v)),Negatives = sum(v<0 & v==-max(abs(v))))
})

然后 运行

df <- cbind(df[1],t(f(df$Beta)))

这样

> df
   Gene Beta Negatives
1   ACE  0.6         1
2  BRCA  0.7         0
3 ZAP70   NA        NA
4   P53  0.8         0