对于R中的循环行为

时间:2012-02-21 14:11:22

标签: r for-loop

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

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

当我在print(organism)循环中for时,它会打印4次Species列,为什么不打印一次?因此,通过我的数据循环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)
}

3 个答案:

答案 0 :(得分:2)

要获得更多“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)])

答案 1 :(得分:1)

dat获取dput(),您可以更改代码以迭代行,并在提取元素之前首先将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)
    }

enter image description here

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

答案 2 :(得分:1)

回答:如果用一个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)}

作为一个愚蠢的例子。