2011-05-04 59 views
4

我读一个CSV文件为R的每一行语句如下:执行,如果对R中

3,3 
3,2 
3,3 
3,3 
3,3 
3,3 
2,3 
1,2 
2,2 
3,3 

我想一个编号分配给各9种独特的可能性,我的数据是(3和3是9,3和2是8,2和3是6等)。我一直试图设计一个嵌套的if语句来评估每一行,在第三列中分配一个数字,并为数据集中的每一行执行此操作。我相信这可以通过apply函数完成,但是我无法在if函数中使用if语句。两列都有可能值1,2或3。这是我的代码迄今,只是想分配一个9至3/3列和0到一切:

#RScript for haplotype analysis 

#remove(list=ls()) 
options(stringsAsFactors=FALSE) 
setwd("C:/Documents and Settings/ColumbiaPC/Desktop") 

#read in comma-delimited, ID-matched genotype data 
OXT <- read.csv("OXTRhaplotype.csv") 
colnames(OXT)<- c("OXT1","OXT2") 

OXT$HAP <- apply(OXT, 1, function(x) if(x[1]=="3"&&x[2]=="3")x[3]=="9" else 0)) 

感谢您的任何提前帮助。

回答

11

你能解决你的描述使用矩阵和标准的R子集的问题,没有任何if陈述

m <- matrix(1:9, nrow=3, byrow=TRUE) 
m 

    [,1] [,2] [,3] 
[1,] 1 2 3 
[2,] 4 5 6 
[3,] 7 8 9 

这可以利用矩阵子集索引m表示:

m[3, 2] 
[1] 8 

m[3,3] 
[1] 9 

m[2,3] 
[1] 6 

现在你可以将此到您的数据:

df <- structure(list(V1 = c(3L, 3L, 3L, 3L, 3L, 3L, 2L, 1L, 2L, 3L), 
     V2 = c(3L, 2L, 3L, 3L, 3L, 3L, 3L, 2L, 2L, 3L)), .Names = c("V1", 
     "V2"), class = "data.frame", row.names = c(NA, -10L)) 

#df$m <- sapply(seq_len(nrow(df)), function(i)m[df$V1[i], df$V2[i]]) 
df$m <- m[as.matrix(df)] # Use matrix subsetting, suggested by @Aaron 
df 

    V1 V2 m 
1 3 3 9 
2 3 2 8 
3 3 3 9 
4 3 3 9 
5 3 3 9 
6 3 3 9 
7 2 3 6 
8 1 2 2 
9 2 2 5 
10 3 3 9 
+1

非常聪明的解决方案! – 2011-05-04 17:10:08

+3

更好的是,用矩阵子集替换'sapply':尝试'[as.matrix(df)]'。 – Aaron 2011-05-04 17:21:22

+0

+1,你是第一个:-) @Aaron(+1)非常好的评论! – chl 2011-05-04 17:35:54

5

不幸的是,我来了晚,类似于@ Andrie的一个解决方案,如:

dat <- matrix(c(3,3,3,2,3,3,3,3,3,3,3,3,2,3,1,2,2,2,3,3), 
       nr=10, byrow=TRUE) 
# here is our lookup table for genotypes 
pat <- matrix(1:9, nr=3, byrow=T, dimnames=list(1:3,1:3)) 

然后

> pat[dat] 
[1] 9 8 9 9 9 9 6 2 5 9 

给你想要的东西。

但是,我想说的是,你可能会发现更容易使用专用包遗传研究,像CRAN发现一个(像geneticsgapSNPassoc,仅举几例)或Bioconductor,因为它们包括设施用于转化/重新编码基因型数据并使用单体型。

这里是什么,我心里有上述言论的例子:

> library(genetics) 
> geno1 <- as.genotype.allele.count(dat[,1]-1) 
> geno2 <- as.genotype.allele.count(dat[,2]-1) 
> table(geno1, geno2) 
    geno2 
geno1 A/A A/B 
    A/A 6 1 
    A/B 1 1 
    B/B 0 1 
5

Andrie的已经通过展示你的问题的一个更好的办法回答你的问题。但是我想提一下你原来的代码中有一些错误。

首先,&&&不一样。有关更多信息,请参见?'&'。我相信你想在你的例子中使用&

其次,==用于测试相等性,您在示例中最初正确使用它。它不用于分配,当您将“9”分配给x[3]时,您不正确地使用它。分配由<-处理,无论是内部函数还是外部函数。有关更多信息,请参阅?'=='?'<-'

第三,在apply()函数内为x[3]赋值并不合理。 apply()只是返回一个数组。它不会修改OXT对象。以下是您的原始方法的外观示例。但是,安德里的方法可能对你更好。

OXT <- read.table(textConnection(
    "3 3 
    3 2 
    3 3 
    3 3 
    3 3 
    3 3 
    2 3 
    1 2 
    2 2 
    3 3")) 
colnames(OXT)<- c("OXT1","OXT2") 

OXT$HAP <- apply(OXT, 1, function(x) 
    { 
     if(x[1] == 3 & x[2] == 3) result <- 9 
     else if(x[1] == 3 & x[2] == 2) result <- 8 
     else if(x[1] == 3 & x[2] == 1) result <- 7 
     else result <- 0 
     return(result) 
    }) 
+0

@jhetzel OP想要匹配9种情况,最终可能会使上述一系列测试变得丑陋;同意休息。 – chl 2011-05-04 17:34:51

+1

@jhetzel - =也可以用于赋值。它通常不是一个好主意,但它可以完成。 – richiemorrisroe 2011-05-04 17:39:58

+0

@chl我同意。要清楚的是,使用一系列条件并不是最好的方法。你和Andrie的方法是要走的路。我只在上面的前三个匹配中包含apply函数,以帮助Bill更好地理解为什么他的原始代码失败。 – jthetzel 2011-05-04 17:50:37

3

另一种方法是将两列粘贴在一起并制作一个因子。

df <- structure(list(V1 = c(3L, 3L, 3L, 3L, 3L, 3L, 2L, 1L, 2L, 3L), 
     V2 = c(3L, 2L, 3L, 3L, 3L, 3L, 3L, 2L, 2L, 3L)), .Names = c("V1", 
     "V2"), class = "data.frame", row.names = c(NA, -10L)) 

df$hap <- factor(paste(df$V1, df$V2, sep="")) 

或等价,

df$hap2 <- factor(apply(df[1:2], 1, paste, collapse="")) 
+0

(+1)是的,好主意,但这将不太容易转变回基因型/单体型数据。 (我认为每列列出DNA序列次要等位基因的频率+1,例如[SNP](http://en.wikipedia.org/wiki/Single-nucleotide_polymorphism),可能编码为1 = AA,2 = AB,3 = BB,B是次要等位基因。) – chl 2011-05-04 17:53:12

+0

正确;这可能不是这种特殊情况下最好的。如果需要组合更多的列或者数据没有如此明确的解释,则可能更合适。 – Aaron 2011-05-04 18:12:06