【问题标题】:How to bin rows by mean then and compute dispersion to identify outliers如何按平均值对行进行分类并计算离散值以识别异常值
【发布时间】:2016-06-24 20:09:12
【问题描述】:

我有一个矩阵,我想根据行均值将所有行分成 20 个箱。我可以按如下方式实现:

library(dplyr)
n_bins = 20
data$bin = ntile(rowMeans(data), n_bins)

现在,在每个 bin 内,我想对 bin 内所有行的离散度度量进行 z 归一化,以识别异常行。我想定义 z 分数截止值为 1.7 的异常值。我不确定是否有一种简单的方法可以解决这个问题,但我目前被困在这一点上。

编辑:

问题重新陈述/澄清:我有一个相当大的 data.frame,有 12374 行(基因)和 785 列(细胞)。我想根据 rowMeans 将行分组到 20 个箱中。在每个箱内,我想对该箱内所有基因的分散测量(方差/平均值)进行 z 归一化,以便识别其表达值高度可变的异常基因,即使与具有相似平均表达的基因相比也是如此。然后我想提取超过 z-score 阈值 1.7 的基因,以从每个 bin 中识别出显着可变的基因。

> head(temp[,1:5])
              Drop7_0_AAACTAGGGTGG Drop7_0_AAAGGACGTACG Drop7_0_AACACTTGAGCC Drop7_0_AAGGCAACGAAT Drop7_0_AATGATGGGGTA
0610007P14RIK            0.1439444            0.0000000             0.000000            0.8759335            0.0000000
0610009B22RIK            0.0000000            0.6776718             0.000000            0.0000000            0.0000000
0610009O20RIK            0.1439444            0.0000000             0.000000            0.2735741            0.0000000
0610010B08RIK            1.4769893            1.1369215             1.124842            0.8759335            1.9544187
0610010F05RIK            0.7944809            0.0000000             0.000000            0.7016789            0.9144108
0610010K14RIK            0.1439444            0.0000000             1.124842            0.7016789            0.0000000

当我运行这段代码时:

library(dplyr)
n_bins = 20
temp = data
temp$rowm = rowMeans(temp)
outscore = temp %>% mutate(bin=ntile(rowm,n_bins)) %>% 
  group_by(bin) %>% mutate(zscore=scale(rowm),outlier=abs(zscore)>1.7)

我得到错误:Error: dims [product 619] do not match the length of object [618] 我认为是指数据中的 bin 数量。

有什么建议吗?

【问题讨论】:

  • 提供一个可重复的好例子将帮助我们帮助您stackoverflow.com/questions/5963269/…
  • 也许使用boxplot(..., plot = FALSE)?或者 hist 休息,如果你愿意的话。
  • @Hack-R,我编辑了我的 OP 以显示我正在使用的一些数据和我拥有的代码。任何见解将不胜感激。
  • @user2117258 太好了,感谢您的额外努力。如果当前的答案不能回答你的问题,我会试一试。
  • @Hack-R,拜托!不幸的是,我仍然坚持这个问题。我将在 OP 中再次重申问题以进行澄清。

标签: r


【解决方案1】:

类似于奥尔顿的回答:

library(dplyr)

n_bins = 20
#making sample data
data = as.data.frame(rbind(replicate(100,rnorm(1000))))

data$rowm = rowMeans(data)

outscore = data %>% mutate(bin=ntile(rowm,n_bins)) %>% 
  group_by(bin) %>% mutate(zscore=scale(rowm),outlier=abs(zscore)>1.7)

scale 对行均值的分布进行归一化,以使整体标准差为 1。“异常值”,在这种情况下,z 分数的大小大于 1.7,标记在 outlier 列中。

如果你想查看哪些行有异常差异,你可以这样做:

outscore$varscore = apply(outscore[,grepl("^V[0-9]+",names(outscore))],1,var)

outscore = outscore %>% mutate(zscore_var = scale(varscore),
  var_outlier = abs(zscore_var) > 1.7)

如果您想使用行均值箱,您也可以使用该分组:

outscore$varscore_grouped = outscore %>% group_by(bin) %>% 
  select(.,starts_with('V')) %>% apply(1,var)

outscore = outscore %>% mutate(zscore_var_grouped = scale(varscore_grouped), 
  var_group_outlier = abs(zscore_var_grouped) > 1.7)

【讨论】:

  • 感谢您的回复。我想对 bin 内所有行的分散度量进行 z 归一化。在这种情况下,离散度定义为方差/均值。
  • 我添加了更多示例,说明如何使用方差而不是均值来衡量异常值。
  • 我似乎无法让我的行名出现在 outscore 中。我遇到了错误:Error: dims [product 619] do not match the length of object [618]
  • 你用过rownames(outscore)吗?
  • 由于我最初的 data 数据框中的行名,我无法制作 outscore 数据框。我正在更新我的 OP。
【解决方案2】:

我想我理解了你的问题。假设Species 是您已经创建的垃圾箱。您可以使用scale 来计算您的标准化分数。

     data(iris)
      iris %>% select(Species,Sepal.Length) %>%
 group_by(Species) %>% mutate(zscore=scale(Sepal.Length))

您按 bin 获得 zscore 或通过 Species 获得这种情况

Species Sepal.Length      zscore
    (fctr)        (dbl)       (dbl)
1   setosa          5.1  0.26667447
2   setosa          4.9 -0.30071802
3   setosa          4.7 -0.86811050
4   setosa          4.6 -1.15180675
5   setosa          5.0 -0.01702177
6   setosa          5.4  1.11776320
7   setosa          4.6 -1.15180675
8   setosa          5.0 -0.01702177
9   setosa          4.4 -1.71919923
10  setosa          4.9 -0.30071802
..     ...          ...         ...

您可以从那里创建一个标志来突出显示这些行 gt abs(1.7)

选项 2:

将所有列转换为行并按组计算 z-score。

  data(iris)
 w <-  iris %>% select(Species,Sepal.Length:Petal.Length) %>%
   gather(features,values,Sepal.Length:Petal.Length) %>% select(-features)
 w$z <- ave(w$values, w$Species, FUN=scale)

选项 3

 library(dplyr)
 n_bins = 20
 temp = data
 temp$rowm = rowMeans(temp)
 outscore = temp %>% mutate(bin=ntile(rowm,n_bins)) 
 outscore$zscore <- ave(outscore$vrowm, outscore$bin, FUN=scale)

希望对你有帮助

【讨论】:

  • 很好,但是分散在哪里计算? scale() 是否也等同于计算所有列的离散度?我的数据设置方式是我有 200 列和 5001 行,其中最后一行是 bin 编号。
  • 好吧,您没有在原始问题中指定这一点 - 如果您可以详细说明,那么我们可以更好地帮助您。您根据您的问题使用ntile 计算rowMeans,然后使用scale 使用group_by 语句获取您的z 分数
  • 你也可以将你的 200 列转换成行,这样scale 就可以毫不费力地工作。很快就会给你一个例子。
  • 添加了第二个选项以防万一
  • 尝试应用此功能时仍有问题。我想对 bin 内所有行的分散度量进行 z 归一化,并定义 abs(z-scores) > 1.7 的行(每个 bin 内)。在这种情况下,离散度定义为方差/均值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-14
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-05
相关资源
最近更新 更多