如何计算R中的合并标准偏差?

如何计算R中的合并标准偏差?,r,function,for-loop,standard-deviation,R,Function,For Loop,Standard Deviation,我想计算数据框中所有唯一站点的汇总(实际加权)标准偏差 这些站点的值是单一物种林分的值,我想将平均值和sd合并,以便比较阔叶林和针叶林。 这是数据框(df),包含阔叶林的值: keybl n mean sd Vest02DenmDesp 3 58.16 6.16 Vest02DenmDesp 5 54.45 7.85 Vest02DenmDesp 3 51.34 1.71 Vest02DenmDesp 3 59.57 5.11

我想计算数据框中所有唯一站点的汇总(实际加权)标准偏差

这些站点的值是单一物种林分的值,我想将平均值和sd合并,以便比较阔叶林和针叶林。
这是数据框(df),包含阔叶林的值:

keybl           n   mean    sd
Vest02DenmDesp  3   58.16   6.16
Vest02DenmDesp  5   54.45   7.85
Vest02DenmDesp  3   51.34   1.71
Vest02DenmDesp  3   59.57   5.11
Vest02DenmDesp  5   62.89   10.26
Vest02DenmDesp  3   77.33   2.14
Mato10GermDesp  4   41.89   12.6
Mato10GermDesp  4   11.92   1.8
Wawa07ChinDesp  18  0.097   0.004
Chen12ChinDesp  3   41.93   1.12
Hans11SwedDesp  2   1406.2  679.46
Hans11SwedDesp  2   1156.2  464.07
Hans11SwedDesp  2   4945.3  364.58
Keybl是站点的代码。合并SD的公式为:

s=sqrt((n1-1)*s1^2+(n2-1)*s2^2)/(n1+n2-2))
(很抱歉,我无法发布图片,也没有找到直接指向公式的链接)

其中2是组数,因此将根据现场情况而变化。我知道这是用来做t检验的,一个人想比较两组。在这种情况下,我不打算比较这些组。我的教授建议我用这个公式得到加权sd。我没有找到一个R函数,它以我需要的方式结合了这个公式,因此我试图建立自己的。然而,我是R新手,不太擅长制作函数和循环,因此我希望得到您的帮助

到目前为止,我得到的是:

sd=function (data) {
nc1=data[z,"nc"]
sc1=data[z, "sc"]
nc2=data[z+1, "nc"]
sc2=data[z+1, "sc"]
sd1=(nc1-1)*sc1^2 + (nc2-1)*sc2^2
sd2=sd1/(nc1+nc2-length(nc1))
sqrt(sd2)
}

splitdf=split(df, with(df, df$keybl), drop = TRUE)

for (c in 1:length(splitdf)) {
for (i in 1:length(splitdf[[i]])) {
    a = (splitdf[[i]])
    b =sd(a)
    }
}
1) 函数本身是不正确的,因为它给出的值比它应该给出的值稍低,我不明白为什么。当z+1到达最后一行时,它是否不会停止?如果是,如何纠正

2) 这个循环是完全错误的,但这是我在几个小时没有成功后所能想到的

有人能帮我吗

谢谢


Antra

你尝试做的事情将受益于一个更通用的公式,这将使它更容易。如果您不需要通过keybl变量将其分解成多个部分,那么您就可以这样做了

dd <- df #df is not a good name for a data.frame variable since df has a meaning in statistics

dd$df <- dd$n-1
pooledSD <- sqrt( sum(dd$sd^2 * dd$df) / sum(dd$df) )
# note, in this case I only pre-calculated df because I'll need it more than once. The sum of squares, variance, etc. are only used once.
现在只需使用方便函数来拆分和计算必要的和。注意这里每个隐式循环只执行一个函数(*apply、aggregate等。所有隐式循环都多次执行函数)


这看起来比其他方法(如42-)要简洁得多,但是如果你根据实际执行的R命令的数量来展开这些方法,这就简洁得多。对于这样一个简短的问题,任何一种方法都可以,但我想我会向你展示使用最多向量数学的方法。它还强调了为什么可以使用这些方便的隐式循环函数来表达。如果您使用
for
循环来完成相同的任务,那么将所有内容放入循环的诱惑会更强烈。这在R中可能是个坏主意。

独立假设下的合并SD(因此协方差项可以假设为零)将是:sqrt(组上的和[(var)/和(n)-n组)])


lappy+split
~
by
?;-)我认识到交叉方差项应该假设为零,这难道不是我的功劳吗?说到你的观点:我有时会避开by,因为它需要
do.call(rbind(.))
来拉回,它看起来很笨重(3个函数而不是两个),但这可能没问题,就像这里的“sapply(split())”一样。我想是款式的问题。非常感谢。这个答案很有效,比我想的要好得多。我只在函数中添加了(dd$n-1),因为sd必须乘以n-1。sum(dd$sd^2*(dd$n-1))表面上看起来更好,但显然存在一个错误,因为WA07CHINDESP应该与原始值相同,因为没有什么可共享的。似乎只有当df始终为2时才是正确的。一个简单的解决方法应该是在分母和(…/sum(dd$n-1))中使用dd$n-1。在我看来,任何时候有单个项目组都可能是错误的。不确定“差异”在这些情况下是否有意义。为什么不立即执行
n-1
sqrt(sum(df$sd^2*(df$n-1))/(sum(df$n-1))
@John为什么你的sdpool值与42的不同?为什么@42有一个答案的Inf?它的可解性如此明显,以至于这个方法是错误的。这里有一个反复检查的方法。如果所有的N都相等,那么合并的方差就是平均方差。Hans11SwedDesp组的方差都等于N的平均值,看看你得到了什么。这里缺少一个括号:s=sqrt(((n1-1)*s1^2+(n2-1)*s2^2)/(n1+n2-2))
# First use R's vector facilities to define the variables you need for pooling.
dd$df <- dd$n-1
dd$s2 <- dd$sd^2 # sd isn't a good name for standard deviation variable even in a data.frame just because it's a bad habit to have... it's already a function and standard deviations have a standard name
dd$ss <- dd$s2 * dd$df
ds <- aggregate(ss ~ keybl, data = dd, sum)
ds$df <- tapply(dd$df, dd$keybl, sum) #two different built in methods for split apply, we could use aggregate for both if we wanted
# divide your ss by your df and voila
ds$s2 <- ds$ss / ds$df
# and also you can easly get your sd
ds$s <- sqrt(ds$s2)
           keybl           ss df           s2          s
1 Chen12ChinDesp 2.508800e+00  2 1.254400e+00   1.120000
2 Hans11SwedDesp 8.099454e+05  3 2.699818e+05 519.597740
3 Mato10GermDesp 4.860000e+02  6 8.100000e+01   9.000000
4 Vest02DenmDesp 8.106832e+02 16 5.066770e+01   7.118125
5 Wawa07ChinDesp 2.720000e-04 17 1.600000e-05   0.004000
     lapply( split(dat, dat$keybl), 
          function(dd) sqrt( sum( dd$sd^2 * (dd$n-1) )/(sum(dd$n-1)-nrow(dd)) ) )
#-------------------------
$Chen12ChinDesp
[1] 1.583919

$Hans11SwedDesp
[1] Inf

$Mato10GermDesp
[1] 11.0227

$Vest02DenmDesp
[1] 9.003795

$Wawa07ChinDesp
[1] 0.004123106