【问题标题】:Performing an if statement on each row in R对 R 中的每一行执行 if 语句
【发布时间】:2011-08-18 17:06:04
【问题描述】:

我正在将一个 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))

提前感谢您的帮助。

【问题讨论】:

    标签: function r syntax apply


    【解决方案1】:

    您可以使用矩阵和标准 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
    

    【讨论】:

    • 更好的是,用矩阵子集替换sapply:试试m[as.matrix(df)]
    • @Aaron。谢谢你的好建议。我已经相应地修改了我的解决方案。
    • 非常感谢您的帮助,我得到了要生成的列。
    【解决方案2】:

    Andrie 已经通过展示解决问题的更好方法回答了您的问题。但是我想提一下您的原始代码中的一些错误。

    首先,&amp;&amp;&amp; 不同。有关更多信息,请参阅?'&amp;'。我相信你想在你的例子中使用&amp;

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

    第三,在apply() 函数中为x[3] 赋值是没有意义的。 apply() 只是返回一个数组。它不会修改OXT 对象。以下是您的原始方法的外观示例。不过,Andrie 的方法可能更适合您。

    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)
        })
    

    【讨论】:

    • @jhetzel OP 想要匹配 9 个案例,这可能会使上述一系列测试在最后变得丑陋;同意其余的。
    • @jhetzel - = 也可用于赋值。这通常不是一个好主意,但可以做到。
    • @chl 我同意。需要明确的是,使用一系列条件不是最好的方法。你和安德烈的方法是要走的路。我只包含上面前三个匹配项的 apply 函数,以帮助 Bill 更好地理解他的原始代码失败的原因。
    • @richiemorrisroe 因为使用= 进行赋值通常不是一个好主意,所以我没有提及。对于那些感兴趣的人,可以快速了解&lt;-= 在 SO 上的对比:stackoverflow.com/questions/1741820/…
    • 哇!感谢大家的大力支持。你是一个非常热情的人群。我确信这是显而易见的,但我对 R 和一般编程非常陌生,我感谢大家花时间更正我的菜鸟代码并提供扩展我知识的解决方案。再次感谢您!
    【解决方案3】:

    不幸的是,我来晚了,解决方案类似于@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
    

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

      • (+1) 是的,好主意,但反过来转换回基因型/单倍型数据不太容易。 (我认为每列索引 DNA 序列 + 1 的次要等位基因的频率,例如SNP,可能编码为 1=AA,2=AB,3=BB,B 是次要等位基因。)
      • 真;在这种特殊情况下,这可能不是最好的事情。如果需要合并的列更多,或者数据没有如此清晰的解释,则可能更合适。
      猜你喜欢
      • 1970-01-01
      • 2020-09-06
      • 1970-01-01
      • 2016-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-17
      相关资源
      最近更新 更多