在一个巨大的文件中更有效地替换因子级别

时间:2015-04-08 02:41:33

标签: r dataframe genome

我有一个包含800000行和13000列的文件。该文件看起来像:

        ID1 ID2 ID3 ID4 ID5
SNP1    AA  AA  AB  AA  BB
SNP2    AB  AA  BB  AA  AA
SNP3    BB  BB  BB  AB  BB
SNP4    AA  AA  BB  BB  AA
SNP5    AA  AA  AA  AA  AA

我想用数字替换字母(AA = 0,AB = 1和BB = 2)。 我所做的是: data [data ==“AA”] = 0 它似乎在一个小例子中正常工作,但它似乎没有在大文件中完成工作。这需要几个小时。有更有效的方法吗? 非常感谢你。 保

3 个答案:

答案 0 :(得分:2)

也许试试这个:

读入您的数据:

DF <- read.table(text = "ID1 ID2 ID3 ID4 ID5
SNP1    AA  AA  AB  AA  BB
SNP2    AB  AA  BB  AA  AA
SNP3    BB  BB  BB  AB  BB
SNP4    AA  AA  BB  BB  AA
SNP5    AA  AA  AA  AA  AA
", header = TRUE, sep = "", stringsAsFactors = FALSE) 

> str(DF)
'data.frame':   5 obs. of  5 variables:
 $ ID1: chr  "AA" "AB" "BB" "AA" ...
 $ ID2: chr  "AA" "AA" "BB" "AA" ...
 $ ID3: chr  "AB" "BB" "BB" "BB" ...
 $ ID4: chr  "AA" "AA" "AB" "BB" ...
 $ ID5: chr  "BB" "AA" "BB" "AA" ...

创建一个查找表:

tab <- c("AA" = 0, "AB" = 1  , "BB" = 2)
> tab
AA AB BB 
 0  1  2

一些分配魔法:

> DF[] <- tab[as.matrix(DF)]
> DF
     ID1 ID2 ID3 ID4 ID5
SNP1   0   0   1   0   2
SNP2   1   0   2   0   0
SNP3   2   2   2   1   2
SNP4   0   0   2   2   0
SNP5   0   0   0   0   0
> str(DF)
'data.frame':   5 obs. of  5 variables:
 $ ID1: num  0 1 2 0 0
 $ ID2: num  0 0 2 0 0
 $ ID3: num  1 2 2 2 0
 $ ID4: num  0 0 1 2 0
 $ ID5: num  2 0 2 0 0

答案 1 :(得分:2)

文件对于R来说可能太大,除非您使用scan,这会使IMO过于复杂化。使用GNU实用程序可以更好地处理这项工作。

如果您在Windows中安装MSYS:

http://www.mingw.org/wiki/Getting_Started

然后使用提到的sed替换文字:

cat <filename>  | sed "s/\bAA\b/0/g" | sed "s/\bBA\b/1/g" | sed "s/\bAB\b/1/g"  | sed "s/\bBB\b/2/g" > <newfile>

编辑:

如果你必须使用R,你可能需要逐行阅读文件,因为文件包含~100亿个条目,其中3个字符中的每一个确实是一个非常大的数据集!

请参阅此处的SO线程以逐行读取文件:

reading a text file in R line by line

但是,我怀疑这会很慢。

答案 2 :(得分:1)

假设您已设法打开文件并假设它是data.framefactor,您可以使用因子已经是1编号的数字列:

DF <- read.table(text = "ID1 ID2 ID3 ID4 ID5
SNP1    AA  AA  AB  AA  BB
SNP2    AB  AA  BB  AA  AA
SNP3    BB  BB  BB  AB  BB
SNP4    AA  AB  BB  BB  AA
SNP5    AA  AA  AA  AA  AA
", header = TRUE, sep = "") 

for (i in seq_along(DF)) {
  # check if the column levels are ordered correctly; if not
  # relevel the column
  if (!identical(levels(DF[[i]]), c("AA", "AB", "BB"))) {
    warning("Levels do not match in column ", i, ". Relevelling.")
    DF[[i]] <- factor(DF[[i]], levels=c("AA", "AB", "BB"))
  }
  # remove the class of the column: this basically makes an integer
  # column from the factor
  attr(DF[[i]], "class") <- NULL
  # substract 1 to get number from 0
  DF[[i]] <- DF[[i]] - 1
}

代码检查级别是否正确编号并在必要时进行重新编译。希望这不会经常发生,因为这会减慢速度。

可能是您的文件不适合内存,这将导致Windows / Linux / ...使用磁盘进行内存存储。这会大大减慢速度。在这种情况下,您最好使用ffbigmemory等软件包。