从数据框的每一列中仅包含离群值。

5

我有一个如下的数据框:

 chr   leftPos         TBGGT     12_try      324Gtt       AMN2
  1     24352           34         43          19         43
  1     53534           2          1           -1         -9
  2      34            -15         7           -9         -18
  3     3443           -100        -4          4          -9
  3     3445           -100        -1          6          -1
  3     3667            5          -5          9           5
  3     7882           -8          -9          1           3

我需要创建一个循环,它需要:

a) 计算从第三列开始每一列的上限和下限(UL和LL)。
b) 只包括不在UL和LL(Zoutliers)之间的行。
c) 然后计算Zoutlier与前一个或后一个同一chr行的方向相同(即正或负)的行数。

因此输出结果为:

 ZScore1    TBGGT     12_try      324Gtt       AMN2
 nrow        4         6            4           4

到目前为止,我已经编写了以下代码:
  library(data.table)#v1.9.5
  f1 <- function(df, ZCol){

  #A) Determine the UL and LL and then generate the Zoutliers
  UL = median(ZCol, na.rm = TRUE) + alpha*IQR(ZCol, na.rm = TRUE)
  LL = median(ZCol, na.rm = TRUE) - alpha*IQR(ZCol, na.rm = TRUE)
  Zoutliers <- which(ZCol > UL | ZCol < LL)

  #B) Exclude Zoutliers per chr if same direction as previous or subsequent row
  na.omit(as.data.table(df)[, {tmp = sign(eval(as.name(ZCol)))
  .SD[tmp==shift(tmp) | tmp==shift(tmp, type='lead')]},
  by=chr])[, list(.N)]}

  nm1 <- paste0(names(df)
  setnames(do.call(cbind,lapply(nm1, function(x) f1(df, x))), nm1)[]

这段代码是从不同的地方拼凑起来的。我的问题是如何将代码的A部分和B部分组合在一起,以获得我想要的输出结果。


“Zcol” 应该是指从第三列开始的所有列,即 3:ncol(df),还是只指一列? - Carl Witthoft
它应该逐列计算。我猜第一部分代码的输出应该给出所有Z异常值及其所在的chr和leftPos,我认为它确实做到了。然后第二部分应该对每个chr取出该列,并按照描述评估每行。这就是想法。那么,我应该将Zoutliers传递到第二部分吗? - Sebastian Zeki
如果我只专注于第一部分 - 我如何获取与chr和leftPos相关联的Zoutliers,然后将其传递给问题的第二部分? - Sebastian Zeki
1个回答

0

你能试试这个函数吗?我不确定alpha是什么,所以无法复现预期的输出,并将其作为变量包含在函数中。

# read your data per copy&paste
d <- read.table("clipboard",header = T)
# or as in Frank comment mentioned solution via fread
d <- data.table::fread("chr   leftPos         TBGGT     12_try      324Gtt       AMN2
                                     1     24352           34         43          19         43
                                     1     53534           2          1           -1         -9
                                     2      34            -15         7           -9         -18
                                     3     3443           -100        -4          4          -9
                                     3     3445           -100        -1          6          -1
                                     3     3667            5          -5          9           5
                                     3     7882           -8          -9          1           3")


# set up the function
foo <- function(x, alpha, chr){
  # your code for task a) and b)
  UL = median(x, na.rm = TRUE) + alpha*IQR(x, na.rm = TRUE)
  LL = median(x, na.rm = TRUE) - alpha*IQR(x, na.rm = TRUE)
  Zoutliers <- which(x > UL | x < LL)
  # part (c
  # factor which specifies the direction. 0 values are set as positives
  pos_neg <- ifelse(x[Zoutliers] >= 0, "positive", "negative")
  # count the occurrence per chromosome and direction.
  aggregate(x[Zoutliers], list(chr[Zoutliers], pos_neg), length)
}

# apply over the columns and get a list of dataframes with number of outliers per chr and direction.
apply(d[,3:ncol(d)], 2, foo, 0.95, d$chr)

1
顺便提一下,该软件包现在提供了fread函数,您可以使用它来读取文本,例如DT= fread("text text text") - Frank
@Frank 哦,好的,谢谢提醒。我已经在我的答案中加入了这个函数。 - Roman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接