AnyMath 文档
Notebook

基于汽车特定范围数据示例的混合效应方差分析

导言

想象一下,你是一名测试工程师,你需要找出不同的车型是否真的在特定的动力储备上有所不同,或者观察到的差异是否只是一个事故,例如与特定工厂 这个问题的答案由方差分析提供,方差分析是一种统计方法,将数据的整体变异性分解为由不同来源引起的部分。 关键思想如下:如果组之间的差异显着超过随机"噪声"的水平,则该因子的影响被识别为显着。

此示例使用混合线性模型。 每个汽车模型充当固定效应,制造商和工厂与模型的相互作用充当随机效应。

训练模型的结果是方差分量,它量化了每个源对整体传播的贡献。:

  • (制造商)-来自不同工厂的汽车平均有多大不同;

  • (制造商×模型)-模型从植物到植物的效果不一致程度(因素的相互作用);

  • (余数)是与汽车的个体特性和测量误差有关的无法解释的变化。

为了直观地表示数据,我们使用箱线图(boxplot,或"带胡子的盒子")。 此图紧凑地显示中位数,四分位数,范围和潜在异常值,使您能够立即估计每个组中的分布中心,其分布和对称性。

boxplot.png

正式假设检验依赖于似然比检验:它将完整模型与减少(无固定效应模型)进行比较,并确定汽车模型的排除是否导致数据描述的统计显着恶化。

通过将混合效应方差分析的能力与表现性统计图形相结合,我们重建了隐藏在测试报告中数字列后面的客观图像。

导入库

我们将添加使用方差分析所需的库。

In [ ]:
# import Pkg
# Pkg.add(["AnovaGLM", "CSV", "DataFrames", "CategoricalArrays", "MixedModels", "Statistics", "Distributions", "GLM", "StatsPlots"])
using AnovaGLM, CSV, DataFrames, CategoricalArrays, MixedModels, Statistics, Distributions, GLM, StatsPlots

初始数据

让我们确定每个车型的特定动力储备的初始数据(пробег). 我们将数据转换为数据对齐的表。

In [ ]:
# 初始数据
来源=[
    33.3  34.5  37.4
    33.4  34.8  36.8
    32.9  33.8  37.6
    32.6  33.4  36.6
    32.5  33.7  37.0
    33.0  33.9  36.7
]

# 实验计划的参数
工厂=3
=6
型号=2
重复=div(行,模型)  
里程=Float64[]
工厂=Int[]
模型=Int[]

力在1:工厂
    对于第1页:行
        推!(里程,初始[,s])
        推!(工厂,z)
        推!(模型,页<=3 1 : 2)
    end
end

# 数据表
=DataFrame(
    哩程=哩程,
    工厂=字符串。(工厂),
    模型=字符串。(型号)
)
表。工厂=分类(表。工厂)
表。模型=分类(表。的模型)

println("汽车的特定动力储备")
println(第一(,18))
汽车的特定动力储备
18×3 DataFrame
 [1m行][1m里程[1m厂[1m型号
     │ Float64  Cat…   Cat…
─────┼────────────────────────
   1 │    33.3  1      1
   2 │    33.4  1      1
   3 │    32.9  1      1
   4 │    32.6  1      2
   5 │    32.5  1      2
   6 │    33.0  1      2
   7 │    34.5  2      1
   8 │    34.8  2      1
   9 │    33.8  2      1
  10 │    33.4  2      2
  11 │    33.7  2      2
  12 │    33.9  2      2
  13 │    37.4  3      1
  14 │    36.8  3      1
  15 │    37.6  3      1
  16 │    36.6  3      2
  17 │    37.0  3      2
  18 │    36.7  3      2

建筑模型

让我们建立一个混合线性模型,其中里程由汽车模型的固定效应和工厂的随机效应以及工厂与模型的相互作用来解释。 让我们使用最大似然法选择模型参数,并分析获得的方差分量和固定效应的估计值。

In [ ]:
公式1=@公式(里程~1+模型+(1/工厂)+(1/工厂和模型))
fit1=fit(MixedModel,公式1,表)
println(选择1)
Minimizing 2    Time: 0:00:00 ( 0.13  s/it)
   objective: 42.098336394833446

Warning: ProgressMeter by default refresh meters with additional information in IJulia via `IJulia.clear_output`, which clears all outputs in the cell. 
 - To prevent this behaviour, do `ProgressMeter.ijulia_behavior(:append)`. 
 - To disable this warning message, do `ProgressMeter.ijulia_behavior(:clear)`.
@ ProgressMeter /usr/local/ijulia-core/packages/ProgressMeter/N660J/src/ProgressMeter.jl:607

Minimizing 34    Time: 0:00:00 (19.87 ms/it)
Linear mixed model fit by maximum likelihood
 里程~1+型号+(1/工厂)+(1|工厂及型号)
   logLik   -2 logLik     AIC       AICc        BIC    
   -12.1071    24.2142    34.2142    39.2142    38.6661

Variance components:
                  Column   Variance Std.Dev. 
工厂及型号(截距)0.0000000.000000
工厂(截获)2.9483211.717068
Residual                    0.093778 0.306232
 Number of obs: 18; levels of grouping factors: 6, 3

  Fixed-effects parameters:
───────────────────────────────────────────────────
                 Coef.  Std. Error      z  Pr(>|z|)
───────────────────────────────────────────────────
(Intercept)  34.9444      0.996591  35.06    <1e-99
型号:2-0.566667 0.144359-3.93<1e-04
───────────────────────────────────────────────────

让我们构建一个没有汽车模型固定效果的缩减混合模型,只留下工厂和交互的随机效应。 让我们在完整模型和缩减模型之间进行似然比测试,以便统计验证汽车模型对里程的影响的显着性。

In [ ]:
公式0=@公式(里程~1+(1/工厂)+(1/工厂和模型))
fit0=fit(MixedModel,formula0,table)
test_pravd=MixedModels。likelihoodratiotest(选择0,选择1)
println("似然比测试结果:")
println(test_pravd)
似然比测试结果:
Model Formulae
1:里程~1+(1/工厂)+(1|工厂及型号)
2:里程~1+车型+(1/厂)+(1|厂&车型)
─────────────────────────────────────────────────
     model-dof  -2 logLik      χ²  χ²-dof  P(>χ²)
─────────────────────────────────────────────────
[1]          4    31.5367                        
[2]          5    24.2142  7.3224       1  0.0068
─────────────────────────────────────────────────

方差分量的估计

让我们使用函数从训练好的模型中提取方差分量 VarCorr 让我们将每个随机效应的数值方差值存储在一个方便的数据结构中。

In [ ]:
组件=VarCorr(选择1)
println(组件)
# 提取方差的函数
函数提取色散(vc)
    string_vc=字符串(vc)
    方差=Dict{String,Float64}()
    for line in split(строка_vc, "\n")
        清洁=条带(线)
        如果isempty(清除)
            continue
        end
        if occursin("Variance components:", очищенная) || 
           occursin("Column", очищенная) || 
           (occursin("Variance", очищенная) && occursin("Std.Dev.", очищенная)) ||
           startswith(очищенная, "──")
            continue
        end
        
        части = split(очищенная, r"\s+")
        如果长度(部分)>=3
            倒数第二=零件[end-1]
            if occursin(r"^\d+\.?\d*$", предпоследнее) || occursin(r"^\d*\.?\d+$", предпоследнее)
                zn=tryparse(Float64,倒数第二)
                如果zn!==没什么
                    имя = join(части[1:end-2], " ")
                    方差[名称]=zn
                end
            end
        end
    end
    方差的返回
end

disp=提取分散体(组分)
σ2_zavod=0.0
σ2_interaction=0.0
σ2_state=0.0

for(k,v)int
    if occursin("制造商及型号", k)
        σ2_interaction=v
    elseif occursin("制造商", k) && !occursin("模型", k)
        σ2_zavod=v
    elseif occursin("Residual", k)
        σ2_state=v
    end
end

println("随机效应差异的估计:")
println("  σ2(制造商)= ", round(σ²_завод, digits=4))
println("  σ2(制造商:型号)= ", round(σ²_взаимодействие, digits=4))
println("  σ2(误差)= ", round(σ²_остаток, digits=4))
Variance components:
                  Column   Variance Std.Dev. 
工厂及型号(截距)0.0000000.000000
工厂(截获)2.9483211.717068
Residual                    0.093778 0.306232

随机效应差异的估计:
  σ2(制造商)=0.0
  σ2(制造商:型号)=0.0
  σ2(误差)=0.0938

结果可视化

让我们设置图形的视觉设计。

In [ ]:
theme(:default)
default(fontfamily="sans-serif", titlefontsize=11, guidefontsize=9, tickfontsize=7)
tsveta_zavodov=[:steelblue,:darkorange,:forestgreen]
color_comp=[:steelblue,:darkorange,:forestgreen]
Out[0]:
3-element Vector{Symbol}:
 :steelblue
 :darkorange
 :forestgreen

使用boxplot,我们将绘制每个制造商的汽车特定动力储备的分布。

In [ ]:
gr()
gr1=@df箱线图表(:工厂,:里程,
    legend=false,
    title="比功率储备的分配",
    xlabel="制造商",
    ylabel="特定动力储备",
    颜色=color_zavodov,
    linewidth=2,
    size=(500, 400))
显示(gr1)
No description has been provided for this image

让我们绘制每个模型的汽车特定动力储备的分布。

In [ ]:
gr2=@df箱线图表(:型号,:里程,
    legend=false,
    title="比功率储备的分配",
    xlabel="汽车模型",
    ylabel="特定动力储备",
    color=[:salmon, :lightblue],
    linewidth=2,
    size=(500, 400))
显示(gr2)
No description has been provided for this image

让我们构建一个制造商-模型交互图。

In [ ]:
mean_zm=combine(groupby(table,[:Factory,:Model]),:Mileage=>mean=>:Average)
中间主义。工厂=字符串。(平均年龄。工厂)
中间主义。模型=字符串。(平均年龄。的模型)
gr3=plot(图例=:bottomright,size=(500,400),
    title="制造商-模型交互时间表",
    xlabel="制造商",
    ylabel="特定动力储备")
colormodels=[:蓝色,:红色]
for (i, мод) in enumerate(["1", "2"])
    数据=平均值[平均值。模特。==国防部,:]
    阴谋!(gr3,数据。工厂,数据。平均,
        marker=:circle, markersize=8, linewidth=2,
        颜色=颜色模型[i],
        label="$Mod模型")
end
显示(gr3)
No description has been provided for this image

让我们按制造商对数据进行分组,并计算每个数据的比功率储备、标准偏差和观测值数。 计算均值和95%置信区间的标准误差。 让我们建立一个具有平均值和误差范围的条形图,以便按特定功率储备直观地比较制造商,并评估获得的估计的准确性。

In [ ]:
stat_zavod=combine(groupby(table,:Factory), 
    :里程=>均值=>:平均值,
    :里程=>std=>:StOtkl,
    :里程=>长度=>:N)
stat_zavod。工厂=字符串。(stat_zavod。工厂)
stat_zavod。错误=stat_zavod。号/sqrt.(stat_zavod。N)
stat_zavod。DI=1.96*stat_zavod。一百个错误

gr4=bar(stat_zavod.工厂,stat_zavod。平均,
    yerror=stat_zavod。迪伊,
    legend=false,
    title="置信区间为95%的分布",
    xlabel="制造商",
    ylabel="特定动力储备",
    颜色=color_zavodov,
    linewidth=2,
    size=(500, 400))
显示器(gr4)
println()
No description has been provided for this image

让我们构建所有观测值的散射图

In [ ]:
таблица.Группа = string.(таблица.Завод) .* "-" .* string.(таблица.Модель)
表。组=分类(表。组)
gr5=plot(图例=:topleft,尺寸=(600,400),
    title="所有关于特定功率储备的观察",
    xlabel="制造商-型号组合",
    ylabel="特定动力储备")
for (i, з) in enumerate(["1", "2", "3"])
    数据=[表。工厂。==z,:]
    散开!(gr5,数据。组,数据。哩程数,
        label="制造商№z",
        颜色=color_zavodov[i],
        markersize=8,
        markerstrokewidth=1.5)
end
显示(gr5)
No description has been provided for this image

让我们建立一个模型和制造商比功率储备分布的热图.

In [ ]:
平均值矩阵=零(工厂,模型)
力在1:工厂
    对于m in1:模型
        掩模=(表。工厂。==字符串(h))。&(.模特。==字符串(m))
        平均值矩阵[z,m]=平均值().里程[面具])
    end
end
гр6 = heatmap(["模型1", "模型2"], 
    ["制造商1", "制造商2", "制造商3"],
    平均矩阵, 
    title="特定动力储备",
    xlabel="模型",
    ylabel="制造商",
    color=:viridis,
    size=(400, 300))
显示(gr6)
No description has been provided for this image

结论

该分析使得将特定动力储备的可变性量化为与汽车模型,制造商及其相互作用相关的组件成为可能。 似然比检验为模型的固定效应的显着性问题提供了正式的答案,并且图形支持—从箱形图到热图-使这些结论清晰可解释。 现在,测试工程师可以不依赖于直觉,而是依赖于统计上可靠的估计:是否值得升级模型的设计或指导统一工厂之间的生产流程。

所考虑的方法是通用的,并且远远超出了汽车行业。 在药品中,它被用来评估药物在不同生产地点之间的作用的可重复性:在农业中,分离植物品种,土壤类型及其对产量的相互作用的影响;在心理学和教育中,当需要考虑受试者的个体差异和实验暴露的影响时。 只要数据具有层次结构(批次内的样本、诊所内的病人、班级内的学生),混合模型就成为正确评估感兴趣的影响和避免因忽略变异性的群体结构而得出错误结论的不可或缺的工具。

因此,掌握本示例中演示的技术为分析各种主题领域中复杂组织的数据提供了一个普遍的机会。