将数据重新排列到矩阵以绘制等高线图

时间:2014-04-25 04:33:17

标签: r plot

我有这些数据:

df = structure(list(vint1 = c(10L, 1L, 1L, 1L, 7L, 10L, 7L, 1L, 8L, 
3L, 7L, 9L, 1L, 5L, 5L), vint2 = c(3L, 4L, 4L, 1L, 3L, 4L, 6L, 
5L, 6L, 3L, 10L, 4L, 1L, 8L, 8L), vnum1 = c(-1.17289752533732, 
-0.559339864207054, -0.595443000061417, -0.396535659893954, 0.788141517690765, 
-0.655833840195406, -2.26371235489487, -1.34850886354386, -0.0218824069117636, 
0.554324892501117, 2.37117531121636, 0.248289029610446, -1.21942427707135, 
-1.4366686196659, -2.64837580107992)), .Names = c("vint1", "vint2", 
"vnum1"), class = "data.frame", row.names = c(NA, -15L))

当我在R提示符上给出以下命令时,它可以工作:

with(df[vint1==10 & vint2==3,], mean(vnum1))  

[1] -1.172898

但是以下函数给出的结果不正确:

testfn = function(df2, a,b,c)
{
    with(df2[df2[[a]]==10 & df2[[b]]==3,], mean(df2[[c]]))
}

当我发出命令时:

testfn(df,1,2,3)

[1] -0.5571128

此值是第3列(vnum1)

中所有条目的平均值
mean(df$vnum1)
[1] -0.5571128

以下功能也不起作用:

testfn = function(df2, name1,name2,name3)
{
    with(df2[name1==10 & name2==3,], mean(name3))
}

如果我使用:with(df2 [df2 $ name1 == 10& df $ name2 == 3,],则表示(df2 $ name3)) 我收到错误: 参数不是数字或逻辑:返回NA

我必须随后将此值分配给创建矩阵,该矩阵可用于创建等高线图:

mycontour = function(df2, a,b,c)
{
    mymat = matrix(0,10,10)
    for(i in 1:10)   for(j in 1:10)
        mymat[i,j]= with(df2[df2[[a]]==i & df2[[b]]==j,], mean(df2[[c]]))
    filled.contour(mymat)
}  

这应该创建一个轮廓图,其中两个有序数(1:10)变量作为x和y轴,轮廓符合第三个(数字)变量(对应于2个因子水平的值的平均值)。我怎么解决这个问题?谢谢你的帮助。

1 个答案:

答案 0 :(得分:0)

在你的第一个函数实例中,

testfn = function(df2, a,b,c)
{
    with(df2[df2[[a]]==10 & df2[[b]]==3,], mean(df2[[c]]))
}

with对你毫无作为。您也可以使用:

testfn2 <- function(df2, a,b,c) {
    mean(df2[df2[[a]]==10 & df2[[b]]==3, c])
}
testfn2(df,1,2,3)
## [1] -1.172898

如果您更喜欢在函数参数中使用名称,则需要 做一些替代魔术。为此,我谦虚地将你推荐给哈德利 威克姆的Subsetting页面 为了彻底的解释。

要创建矩阵,再次使用with无效。试试这个:

mycontour2 <- function(df2, a,b,c) {
    nr <- 10 ; nc <- 10
    mm <- matrix(0, nr=nr, nc=nc)
    for (i in 1:nr)
        for (j in 1:nc)
            mm[i,j] <- mean(df2[df2[[a]]==i & df2[[b]]==j, c])
    mm[is.nan(mm)] <- 0
    mm
}
round(mycontour2(df, 1,2,3), digits=2)
##       [,1] [,2]  [,3]  [,4]  [,5]  [,6] [,7]  [,8] [,9] [,10]
##  [1,] -0.81    0  0.00 -0.58 -1.35  0.00    0  0.00    0  0.00
##  [2,]  0.00    0  0.00  0.00  0.00  0.00    0  0.00    0  0.00
##  [3,]  0.00    0  0.55  0.00  0.00  0.00    0  0.00    0  0.00
##  [4,]  0.00    0  0.00  0.00  0.00  0.00    0  0.00    0  0.00
##  [5,]  0.00    0  0.00  0.00  0.00  0.00    0 -2.04    0  0.00
##  [6,]  0.00    0  0.00  0.00  0.00  0.00    0  0.00    0  0.00
##  [7,]  0.00    0  0.79  0.00  0.00 -2.26    0  0.00    0  2.37
##  [8,]  0.00    0  0.00  0.00  0.00 -0.02    0  0.00    0  0.00
##  [9,]  0.00    0  0.00  0.25  0.00  0.00    0  0.00    0  0.00
## [10,]  0.00    0 -1.17 -0.66  0.00  0.00    0  0.00    0  0.00

另一种接近但不包括缺失指数的方式:

require(reshape2)
round(acast(df, vint1 ~ vint2, value.var='vnum1', fun.aggregate=mean, fill=0), digits=3)
##       1     3     4     5     6     8   10
## 1  -0.81  0.00 -0.58 -1.35  0.00  0.00 0.00
## 3   0.00  0.55  0.00  0.00  0.00  0.00 0.00
## 5   0.00  0.00  0.00  0.00  0.00 -2.04 0.00
## 7   0.00  0.79  0.00  0.00 -2.26  0.00 2.37
## 8   0.00  0.00  0.00  0.00 -0.02  0.00 0.00
## 9   0.00  0.00  0.25  0.00  0.00  0.00 0.00
## 10  0.00 -1.17 -0.66  0.00  0.00  0.00 0.00

请注意,第2列和第7列缺失,第2,4和6行都是缺失的 其中在前一个矩阵中为零。如果你有一个更大的 那么你没有错过任何x或y值的数据集 也许这对你有用。 (有办法解决这个问题, 但是,如果你需要它更强大。如果是这样,那就好了。)