【问题标题】:For loop behaviour in RR中的for循环行为
【发布时间】:2012-02-21 14:11:22
【问题描述】:

我正在尝试在我的R 代码中使用for 循环和if 语句,如下所示。

它会生成一个密度图,然后我尝试在密度上添加一条垂直线,该密度按物种着色。

当我在 for 循环中 print(organism) 时,它会打印 Species 列 4 次,为什么不打印一次?因此,它是否会在我的数据中循环 4 次?

代码设法在密度图中添加了一些红线,但为什么没有为其他物种添加剩余的彩色线?

dat <- structure(list(pdb = structure(1:13, .Label = c("1akk.pdb", "1fi7.pdb", 
"1fi9.pdb", "1giw.pdb", "1hrc.pdb", "1i5t.pdb", "1j3s0.10.pdb", 
"1j3s0.11.pdb", "1j3s0.12.pdb", "1j3s0.13.pdb", "1j3s0.14.pdb", 
"2aiu.pdb", "2b4z.pdb"), class = "factor"), PA = c(1128, 1143, 
1119, 1130, 1055, 1112, 1120, 1121, 1135, 1102, 1121, 1037, 1179
), EHSS = c(1424, 1439, 1404, 1423, 1318, 1403, 1412, 1415, 1432, 
1391, 1413, 1299, 1441), Species = structure(c(2L, 2L, 2L, 2L, 
2L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 1L), .Label = c("BOSTAURUS", 
"EQUUSCABALLUS", "HOMOSAPIENS", "MUSMUSCULUS"), class = "factor")), .Names = c("pdb", 
"PA", "EHSS", "Species"), class = "data.frame", row.names = c(NA, 
-13L))

den.PA <- density(dat$PA)
plot(den.PA)

for (i in 1:length(dat)){
    lineat = dat$PA[i]
    organism = dat$Species[i]
    lineheight <- den.PA$y[which.min(abs(den.PA$x - lineat))]
    print (organism)
    if (organism == 'EQUUSCABALLUS'){
        col = 'red'
    }
    if (organism == 'HOMOSAPIENS'){
        col = 'blue'
    }
    if (organism == 'MUSMUSCULUS'){
        col = 'green'
    }
    if (organism == 'BOSTAURUS'){
        col = 'purple'
    }
    lines(c(lineat, lineat), c(0, lineheight), col = col)
}

【问题讨论】:

  • 您的 read.table() 语句不会为我生成可用的对象。如果您有一个名为dat 的看似正常的对象,您如何为我们复制并粘贴dput(dat) 的控制台输出?
  • dput(dat) 输出在上面
  • 而您的循环仅执行 1:4,因为 data.framelist,而 data.framelength() 是其列数。

标签: r for-loop


【解决方案1】:

对于更“R-ish”的解决方案,请尝试将matchapproxpoints 与直方图类型一起使用。

den.PA <- density(dat$PA)
cols <- data.frame(Species=c('EQUUSCABALLUS', 'HOMOSAPIENS', 'MUSMUSCULUS', 'BOSTAURUS'),
                   col=c('red', 'blue', 'green', 'purple'), stringsAsFactors=FALSE)
plot(den.PA)
points(approx(den.PA$x, den.PA$y, dat$PA), type="h", 
       col=cols$col[match(dat$Species, cols$Species)])

【讨论】:

  • 同意,我尝试使用一堆嵌套的ifelse() 语句将它塞进对segments() 的单个调用中并放弃了。 +1 为 R-ness
【解决方案2】:

dput() 获取dat,您可以更改代码以迭代行,并在提取元素之前先将PA 转换为character 类。这样你会得到 13 行:

    den.PA <- density(dat$PA)
    plot(den.PA)

    for (i in 1:nrow(dat)){
        lineat <- dat$PA[i]
        organism <- as.character(dat$Species)[i]
        lineheight <- den.PA$y[which.min(abs(den.PA$x - lineat))]
        print (organism)
        if (organism == 'EQUUSCABALLUS'){
            col <- 'red'
        }
        if (organism == 'HOMOSAPIENS'){
            col <- 'blue'
        }
        if (organism == 'MUSMUSCULUS'){
            col <- 'green'
        }
        if (organism == 'BOSTAURUS'){
            col <- 'purple'
        }
        segments(lineat,0,lineat,lineheight,col=col)
    }

另外,我将 lines() 更改为 segments(),因为您只有 2 分。然而,这并没有太大的区别。我还将使用= 的声明更改为&lt;-,这对大多数R 用户的眼睛伤害较小。

【讨论】:

    【解决方案3】:

    侧面答案:如果将所有 if 替换为单个 switch 构造,您将获得更流畅的代码。

    来自帮助页面:

     centre <- function(x, type) {
         + switch(type,
         +        mean = mean(x),
         +        median = median(x),
         +        trimmed = mean(x, trim = .1))
         + }
    

    这里的好处之一是您可以在任何箱子的右侧放置任意数量的物品。例如在我发布的示例中,您可以这样做:
    + mean = {cat"this is the mean"; y=mean(x)*sin(z);plot(z,y)}

    作为一个愚蠢的例子。

    【讨论】:

      猜你喜欢
      • 2016-01-26
      • 1970-01-01
      • 2013-12-12
      • 1970-01-01
      • 2021-04-13
      • 1970-01-01
      • 2013-02-12
      • 1970-01-01
      • 2011-01-31
      相关资源
      最近更新 更多