-2

我正在尝试根据两个分组(门和环境)计算平均值(以及其他计算),并且我想重定向到输出到文件。我知道下面的代码有效。

new_df = myDF[(myDF$Environment=='Water_MarineTreated') & (myDF$Phylum=='Acidobacteria'),]
print(mean(new_df$pH))

但是,由于环境如此之多,门类繁多,我觉得包含循环的函数是最好的方法。我有一个函数,它采用向量的名称和计算的名称(例如,平均值、标准差、变量等)循环遍历每个环境和每个门,计算每个排列的平均 pH 值,将其添加到向量,返回向量。不幸的是,返回值为“numeric(0)”。虽然这正在返回我告诉它的内容,但这不是我想要的。

我认为规则是每个帖子一个问题,所以如果有人可以解释为什么有一个返回的空向量而不是一个充满 pH 值的向量,我将不胜感激。如果规则可以稍微弯曲并且有人可以回答为什么“eName = numeric()”不起作用,我也会很感激。如果我在内循环中放置一个虚拟打印语句,当我使用 eName = numeric() 时,不会打印任何内容,就像我初始化 Water_MarineTreatated = numeric() 一样,打印的虚拟语句。

我的函数和函数调用如下所示。

    fileName = 'mini.txt'    
    myDF = read.csv(fileName, header = TRUE, sep = ' ')
    environment = unique(unlist(myDF$Environment, use.names = FALSE))
    phyla = unique(unlist(myDF$Phylum, use.names = FALSE))

    Statistics = function(eName, funName)
    {
       #eName = numeric() #This approach does not work?!!
       for (i in environment)
       {   
          for (j in phyla)
          {   
             stats_df = myDF[(myDF$Environment==i) & (myDF$Phylum==j),]

             if (i == deparse(substitute(eName)))
             {   
                #Water_MarineTreated == c(Water_MarineTreated, funName(as.numeric(stats_df$pH)))
                eName == c(eName, funName(as.numeric(stats_df$pH)))
                print('dummy_statement')
              }   
          }   
       }   
       return(eName)
    }

    Water_MarineTreated = numeric()
    Water_MarineTreated = Statistics(Water_MarineTreated, mean)
    print(Water_MarineTreated)

输入示例如下所示:

Phylum pH Environment 
Acidobacteria 5.4 Water_MarineTreated 
Acidobacteria 6.1 Water_PondTreated
Acidobacteria 6.1 Water_MarineTreated 
Acidobacteria 5.6 Water_MarineTreated 
Acidobacteria 6.2 Water_MarineTreated 
Deinococcus_Thermus 4.9 Water_MarineTreated 
Firmicutes 5.1 Water_MarineTreated 
Firmicutes 5.5 Water_MarineTreated 
4

3 回答 3

2

data.table软件包(除其他外)提供了一种非常好的语法,用于按组快速计算函数。考虑以下示例:

library(data.table)

# Convert sample data to a data.table:
dt <- as.data.table(mtcars)

# Calculate the mean and median mpg by cyl and gear, where carb < 8:
dt[carb<8, # The "where clause"
   list(mpg.mean=mean(mpg), mpg.med=median(mpg)), # What you want to calculate
   by=list(cyl,gear)] # The groups go here
#   cyl gear mpg.mean mpg.med
#1:   6    4   19.750   20.10
#2:   4    4   26.925   25.85
#3:   6    3   19.750   19.75
#4:   8    3   15.050   15.20
#5:   4    3   21.500   21.50
#6:   4    5   28.200   28.20
#7:   8    5   15.800   15.80
#8:   6    5   19.700   19.70

查看文档了解更多信息。

于 2013-10-05T21:01:50.877 回答
2

您的解决方案可以使用plyr包获得:

library(plyr)
ddply(mtcars,.(mpg,cyl),colwise(mean))

对于您的数据,如果您试图找到除 E​​nvironment 和 Phylum 之外的所有列的平均值(并假设这些是数字)

library(plyr)
 ddply(myDF,.(Environment,Phylum),colwise(mean))

注意:如果需要 sd,请将 mean 替换为 sd。

于 2013-10-05T21:14:27.970 回答
2

您在循环的中间有以下行:

eName == c(eName, funName(as.numeric(stats_df$pH)))

双等号==表示比较并返回一个TRUEor FALSE,它不做任何赋值。所以eName从一个空向量开始,并且从来没有分配任何东西。这只是我喜欢<-分配的原因之一。

即使你切换到一个赋值,现在你会覆盖每次迭代的值,返回值将只是最终值,而不是全部。你需要更多类似的东西:

eName[i] <- ...

或者

eName[i,] <- ...

尽管在这两种情况下,它通常比sapply循环更容易使用。

于 2013-10-05T21:16:30.163 回答