2011-05-04 57 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