T 检验聚合

编辑

t_test 指标聚合执行统计假设检验,其中检验统计量在零假设下遵循从聚合文档中提取的数值的 Student t 分布。实际上,这将告诉您两个总体均值之间的差异是否具有统计学意义,而不仅仅是偶然发生。

语法

编辑

一个 t_test 聚合单独使用时如下所示

{
  "t_test": {
    "a": "value_before",
    "b": "value_after",
    "type": "paired"
  }
}

假设我们有升级前后节点启动时间的记录,让我们看看 t 检验,看看升级是否以有意义的方式影响了节点启动时间。

resp = client.search(
    index="node_upgrade",
    size=0,
    aggs={
        "startup_time_ttest": {
            "t_test": {
                "a": {
                    "field": "startup_time_before"
                },
                "b": {
                    "field": "startup_time_after"
                },
                "type": "paired"
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'node_upgrade',
  body: {
    size: 0,
    aggregations: {
      startup_time_ttest: {
        t_test: {
          a: {
            field: 'startup_time_before'
          },
          b: {
            field: 'startup_time_after'
          },
          type: 'paired'
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "node_upgrade",
  size: 0,
  aggs: {
    startup_time_ttest: {
      t_test: {
        a: {
          field: "startup_time_before",
        },
        b: {
          field: "startup_time_after",
        },
        type: "paired",
      },
    },
  },
});
console.log(response);
GET node_upgrade/_search
{
  "size": 0,
  "aggs": {
    "startup_time_ttest": {
      "t_test": {
        "a": { "field": "startup_time_before" },  
        "b": { "field": "startup_time_after" },   
        "type": "paired"                          
      }
    }
  }
}

字段 startup_time_before 必须是数值字段。

字段 startup_time_after 必须是数值字段。

由于我们有来自相同节点的数据,因此我们使用配对 t 检验。

响应将返回检验的 p 值或概率值。它是获得至少与聚合处理的结果一样极端的结果的概率,假设零假设是正确的(这意味着总体均值之间没有差异)。较小的 p 值意味着零假设更可能是错误的,并且总体均值确实不同。

{
  ...

 "aggregations": {
    "startup_time_ttest": {
      "value": 0.1914368843365979 
    }
  }
}

p 值。

T 检验类型

编辑

t_test 聚合支持非配对和配对的双样本 t 检验。可以使用 type 参数指定检验类型

"type": "paired"
执行配对 t 检验
"type": "homoscedastic"
执行双样本等方差检验
"type": "heteroscedastic"
执行双样本不等方差检验(这是默认值)

过滤器

编辑

也可以使用过滤器在不同的记录集上运行非配对 t 检验。例如,如果我们想测试两组不同节点升级前的启动时间差异,我们使用相同的字段 startup_time_before,并通过组名称字段上的 terms 过滤器来分离节点组

resp = client.search(
    index="node_upgrade",
    size=0,
    aggs={
        "startup_time_ttest": {
            "t_test": {
                "a": {
                    "field": "startup_time_before",
                    "filter": {
                        "term": {
                            "group": "A"
                        }
                    }
                },
                "b": {
                    "field": "startup_time_before",
                    "filter": {
                        "term": {
                            "group": "B"
                        }
                    }
                },
                "type": "heteroscedastic"
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'node_upgrade',
  body: {
    size: 0,
    aggregations: {
      startup_time_ttest: {
        t_test: {
          a: {
            field: 'startup_time_before',
            filter: {
              term: {
                group: 'A'
              }
            }
          },
          b: {
            field: 'startup_time_before',
            filter: {
              term: {
                group: 'B'
              }
            }
          },
          type: 'heteroscedastic'
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "node_upgrade",
  size: 0,
  aggs: {
    startup_time_ttest: {
      t_test: {
        a: {
          field: "startup_time_before",
          filter: {
            term: {
              group: "A",
            },
          },
        },
        b: {
          field: "startup_time_before",
          filter: {
            term: {
              group: "B",
            },
          },
        },
        type: "heteroscedastic",
      },
    },
  },
});
console.log(response);
GET node_upgrade/_search
{
  "size": 0,
  "aggs": {
    "startup_time_ttest": {
      "t_test": {
        "a": {
          "field": "startup_time_before",         
          "filter": {
            "term": {
              "group": "A"                        
            }
          }
        },
        "b": {
          "field": "startup_time_before",         
          "filter": {
            "term": {
              "group": "B"                        
            }
          }
        },
        "type": "heteroscedastic"                 
      }
    }
  }
}

字段 startup_time_before 必须是数值字段。

这里可以使用任何分隔两组的查询。

我们使用相同的字段

但我们使用不同的过滤器。

由于我们有来自不同节点的数据,因此我们不能使用配对 t 检验。

{
  ...

 "aggregations": {
    "startup_time_ttest": {
      "value": 0.2981858007281437 
    }
  }
}

p 值。

总体不必在同一个索引中。如果数据集位于不同的索引中,则可以使用 _index 字段上的 term 过滤器来选择总体。

脚本

编辑

如果您需要在并非由字段清晰表示的值上运行 t_test,则应该在运行时字段上运行聚合。例如,如果您想调整之前值的加载时间

resp = client.search(
    index="node_upgrade",
    size=0,
    runtime_mappings={
        "startup_time_before.adjusted": {
            "type": "long",
            "script": {
                "source": "emit(doc['startup_time_before'].value - params.adjustment)",
                "params": {
                    "adjustment": 10
                }
            }
        }
    },
    aggs={
        "startup_time_ttest": {
            "t_test": {
                "a": {
                    "field": "startup_time_before.adjusted"
                },
                "b": {
                    "field": "startup_time_after"
                },
                "type": "paired"
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'node_upgrade',
  body: {
    size: 0,
    runtime_mappings: {
      'startup_time_before.adjusted' => {
        type: 'long',
        script: {
          source: "emit(doc['startup_time_before'].value - params.adjustment)",
          params: {
            adjustment: 10
          }
        }
      }
    },
    aggregations: {
      startup_time_ttest: {
        t_test: {
          a: {
            field: 'startup_time_before.adjusted'
          },
          b: {
            field: 'startup_time_after'
          },
          type: 'paired'
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "node_upgrade",
  size: 0,
  runtime_mappings: {
    "startup_time_before.adjusted": {
      type: "long",
      script: {
        source: "emit(doc['startup_time_before'].value - params.adjustment)",
        params: {
          adjustment: 10,
        },
      },
    },
  },
  aggs: {
    startup_time_ttest: {
      t_test: {
        a: {
          field: "startup_time_before.adjusted",
        },
        b: {
          field: "startup_time_after",
        },
        type: "paired",
      },
    },
  },
});
console.log(response);
GET node_upgrade/_search
{
  "size": 0,
  "runtime_mappings": {
    "startup_time_before.adjusted": {
      "type": "long",
      "script": {
        "source": "emit(doc['startup_time_before'].value - params.adjustment)",
        "params": {
          "adjustment": 10
        }
      }
    }
  },
  "aggs": {
    "startup_time_ttest": {
      "t_test": {
        "a": {
          "field": "startup_time_before.adjusted"
        },
        "b": {
          "field": "startup_time_after"
        },
        "type": "paired"
      }
    }
  }
}