【问题标题】:Filter/Split dataframe in 3 groups according to row values根据行值在 3 组中过滤/拆分数据帧
【发布时间】:2011-10-21 21:53:26
【问题描述】:

我不确定标题是否足够清楚。 我有一个数据框(见下文),其中包含 5 列的值。我想做的是将此数据框“拆分”为三个类,其中行可以分配为“高”、“中”、“低”状态。

我的意思是:

高:至少 3 列中的值“高”

中等:至少 3 列中的值为“中等”

低:至少 3 列中的值为“低”(或 NA

我猜它涉及两件事,定义 3 个组的值截止,然后将行分配到高、中和低类别...但这是一个猜测

数据文件为available here

tmp = read.table("tmp2.txt", header=TRUE)
head(tmp)
           Geneid     Hsap      Mmul      Mmus      Rnor     Cfam
1 ENSG00000197711 365823.5 243429.20 44337.267 156874.50 128015.0
2 ENSG00000198712 198613.0        NA 47767.767 200176.50 210559.8
3 ENSG00000198899 189421.5        NA        NA 283425.50 367112.8
4 ENSG00000198804 182559.5        NA 87301.900 277861.00 324438.0
5 ENSG00000198840 142424.5        NA  8400.457  45844.80 115027.9
6 ENSG00000171564 119147.9  93564.66  6675.290  45938.85  45140.2

非常感谢任何建议,因为我对如何解决这个问题一无所知!

谢谢,


这是下面的答案:

我现在已将文件替换为更真实的文件(更多行)

tbl <- read.csv("http://db.tt/L2ehGh8", header=FALSE)
colnames(tbl) <- c("Geneid","Hsap","Mmul","Mmus","Rnor","Cfam")

使用 cut() : 我有很多 0,而且值很安静,所以通过使用 log 或这里的 asinh,你可以摆脱它。

tbl.data <- apply(asinh(tbl.data),2,
                  function(x) as.numeric(as.factor(cut(x,4)))  )
head(tbl.data)
     Hsap Mmul Mmus Rnor Cfam
[1,]    2    2    1    1    2
[2,]    2    2    2    2    2
[3,]    1    1    1    1    1
[4,]    1    1    1    1    1
[5,]    2    3    2    2    3
[6,]    2    2    2    2    2

另一种方法是使用分位数,正如我所看到的那样。

quantile(tbl.data[,1],0.25)
quantile(tbl.data[,1],0.5)
quantile(tbl.data[,1],0.75)

tbl.data2 <- apply(tbl.data,2,
                   function(x) as.numeric(as.factor(cut(x,c(-1,
                       quantile(x, 0.25)+0.0001,
                       quantile(x,0.5),
                       quantile(x,0.75), max(x))))))
head(tbl.data2)
     Hsap Mmul Mmus Rnor Cfam
[1,]    3    3    3    2    3
[2,]    2    3    4    3    3
[3,]    2    1    1    1    2
[4,]    1    2    1    1    1
[5,]    4    4    4    4    4
[6,]    3    4    4    3    4

【问题讨论】:

  • 您想要生成 3 个单独的 data.frames 吗?还是只想添加另一列分配给低、中或高?
  • 你应该避免使用t作为变量名,因为它是一个内部函数(转置矩阵)。
  • 任何一种方式都可以——我想最方便的方法是增加一个带有 (H, M, L) 或类似内容的列
  • 如果根据各个列的值将这 5 列分成三分位数,您将得到一堆没有指定类别的 H H M L L 或 M M H H L 或 NA NA M H H 行。你想丢弃它们吗?
  • 有未定义的情况。当连续出现 2 个高点、1 个中点和 2 个低点时,你会怎么做?它被归类为什么?

标签: r filter matrix split dataframe


【解决方案1】:

假设您希望通过不计算它们而不是折腾整行来处理 NAs:

tbl <- read.table("http://db.tt/Eb6qM4h",header=TRUE)
tbl.data <- subset(tbl,select=-Geneid)
tbl.data <- apply(tbl.data,2,function(x) as.numeric(as.factor(cut(x,3)))  )


countLevels <- function(tbl.data,lvl) {
  apply(tbl.data,1,function(x) sum( x[!is.na(x)] == lvl ) )
}

tbl.final <- tbl.new <- subset(tbl,select=Geneid)
for(lvl in seq(3) ) {
  tbl.new[,paste('Level',lvl)] <- (countLevels(tbl.data,lvl) > 3) * lvl
}

tbl.final$Levels <- rowSums(subset(tbl.new,select=-Geneid))

返回data.frame如下:

> head(tbl.final,20)
            Geneid Levels
1  ENSG00000197711      0
2  ENSG00000198712      0
3  ENSG00000198899      0
4  ENSG00000198804      0
5  ENSG00000198840      0
6  ENSG00000171564      1
7  ENSG00000171557      1
8  ENSG00000198727      1
9  ENSG00000163631      0
10 ENSG00000198888      1
11 ENSG00000198695      1
12 ENSG00000198763      1
13 ENSG00000198786      1
14 ENSG00000158874      0
15 ENSG00000138207      1
16 ENSG00000109072      1
17 ENSG00000130203      3
18 ENSG00000106927      1
19 ENSG00000110169      1
20 ENSG00000104760      1

【讨论】:

  • 感谢 gsk3 - 我了解您对“tbl.data”的操作,但我不确定我是否了解 tbl.new!单行可以是高、中或低,所以,我在这里有点困惑。也许我错过了什么
  • 如果您希望它作为一个单独的列来捕获所有 3 个级别,我已将其更改为一种方法。不幸的是,数据似乎没有任何三个都在中间或高组中,所以它没有显示出来,但它应该给你 Level=={1,2,3}。我假设您希望更实质性地将事物分为 l/m/h 类别; cut 真的只是一个占位符....
  • 感谢 gsk3 - 我现在正在使用包含更多行的数据框。但是,在应用您的代码时,我只会获得“1”级。奇数。
  • 第 17 行有 3 个高分组,并且似乎有效。添加了更多输出,您可以在上面看到。
猜你喜欢
  • 1970-01-01
  • 2021-10-25
  • 2022-10-02
  • 1970-01-01
  • 1970-01-01
  • 2012-08-13
  • 1970-01-01
  • 1970-01-01
  • 2013-04-07
相关资源
最近更新 更多