Выполнение оператора if в каждой строке в R - PullRequest
4 голосов
/ 04 мая 2011

Я читаю в CSV-файл в 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 работал внутри функции apply. Оба столбца имеют возможные значения 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))

Спасибо за любую помощь заранее.

Ответы [ 4 ]

11 голосов
/ 04 мая 2011

Вы можете решить проблему, которую вы описываете, используя матрицу и стандартное подмножество 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
5 голосов
/ 04 мая 2011

Андри уже ответил на ваш вопрос, показывая лучший подход к вашей проблеме.Но в вашем исходном коде есть несколько ошибок, о которых я хочу упомянуть.

Во-первых, & - это не то же самое, что &&.Смотрите ?'&' для более.Я полагаю, что вы хотели использовать & в своем примере.

Во-вторых, == используется для тестов на равенство, которые вы изначально правильно использовали в своем примере.Он не используется для назначения, для которого вы неправильно используете его при назначении «9» для x[3].Назначение обрабатывается <- как внутри, так и вне функций.Подробнее см. ?'==' и ?'<-'.

В-третьих, присвоение значения x[3] в функции apply() не имеет смысла.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)
    })
5 голосов
/ 04 мая 2011

К сожалению, я опоздал, и с решением, похожим на @ 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 (например, genetics, gap или SNPassoc,несколько) или 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
3 голосов
/ 04 мая 2011

Другой подход состоит в том, чтобы вставить две колонки вместе и получить коэффициент.

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=""))
...