|
| 1 | +[role="xpack"] |
| 2 | +[testenv="basic"] |
| 3 | +[[search-aggregations-metrics-ttest-aggregation]] |
| 4 | +=== TTest Aggregation |
| 5 | + |
| 6 | +A `t_test` metrics aggregation that performs a statistical hypothesis test in which the test statistic follows a Student's t-distribution |
| 7 | +under the null hypothesis on numeric values extracted from the aggregated documents or generated by provided scripts. In practice, this |
| 8 | +will tell you if the difference between two population means are statistically significant and did not occur by chance alone. |
| 9 | + |
| 10 | +==== Syntax |
| 11 | + |
| 12 | +A `t_test` aggregation looks like this in isolation: |
| 13 | + |
| 14 | +[source,js] |
| 15 | +-------------------------------------------------- |
| 16 | +{ |
| 17 | + "t_test": { |
| 18 | + "a": "value_before", |
| 19 | + "b": "value_after", |
| 20 | + "type": "paired" |
| 21 | + } |
| 22 | +} |
| 23 | +-------------------------------------------------- |
| 24 | +// NOTCONSOLE |
| 25 | + |
| 26 | +Assuming that we have a record of node start up times before and after upgrade, let's look at a t-test to see if upgrade affected |
| 27 | +the node start up time in a meaningful way. |
| 28 | + |
| 29 | +[source,console] |
| 30 | +-------------------------------------------------- |
| 31 | +GET node_upgrade/_search |
| 32 | +{ |
| 33 | + "size": 0, |
| 34 | + "aggs" : { |
| 35 | + "startup_time_ttest" : { |
| 36 | + "t_test" : { |
| 37 | + "a" : {"field": "startup_time_before"}, <1> |
| 38 | + "b" : {"field": "startup_time_after"}, <2> |
| 39 | + "type": "paired" <3> |
| 40 | + } |
| 41 | + } |
| 42 | + } |
| 43 | +} |
| 44 | +-------------------------------------------------- |
| 45 | +// TEST[setup:node_upgrade] |
| 46 | +<1> The field `startup_time_before` must be a numeric field |
| 47 | +<2> The field `startup_time_after` must be a numeric field |
| 48 | +<3> Since we have data from the same nodes, we are using paired t-test. |
| 49 | + |
| 50 | +The response will return the p-value or probability value for the test. It is the probability of obtaining results at least as extreme as |
| 51 | +the result processed by the aggregation, assuming that the null hypothesis is correct (which means there is no difference between |
| 52 | +population means). Smaller p-value means the null hypothesis is more likely to be incorrect and population means are indeed different. |
| 53 | + |
| 54 | +[source,console-result] |
| 55 | +-------------------------------------------------- |
| 56 | +{ |
| 57 | + ... |
| 58 | +
|
| 59 | + "aggregations": { |
| 60 | + "startup_time_ttest": { |
| 61 | + "value": 0.1914368843365979 <1> |
| 62 | + } |
| 63 | + } |
| 64 | +} |
| 65 | +-------------------------------------------------- |
| 66 | +// TESTRESPONSE[s/\.\.\./"took": $body.took,"timed_out": false,"_shards": $body._shards,"hits": $body.hits,/] |
| 67 | +<1> The p-value. |
| 68 | + |
| 69 | +==== T-Test Types |
| 70 | + |
| 71 | +The `t_test` aggregation supports unpaired and paired two-sample t-tests. The type of the test can be specified using the `type` parameter: |
| 72 | + |
| 73 | +`"type": "paired"`:: performs paired t-test |
| 74 | +`"type": "homoscedastic"`:: performs two-sample equal variance test |
| 75 | +`"type": "heteroscedastic"`:: performs two-sample unequal variance test (this is default) |
| 76 | + |
| 77 | +==== Script |
| 78 | + |
| 79 | +The `t_test` metric supports scripting. For example, if we need to adjust out load times for the before values, we could use |
| 80 | +a script to recalculate them on-the-fly: |
| 81 | + |
| 82 | +[source,console] |
| 83 | +-------------------------------------------------- |
| 84 | +GET node_upgrade/_search |
| 85 | +{ |
| 86 | + "size": 0, |
| 87 | + "aggs" : { |
| 88 | + "startup_time_ttest" : { |
| 89 | + "t_test" : { |
| 90 | + "a": { |
| 91 | + "script" : { |
| 92 | + "lang": "painless", |
| 93 | + "source": "doc['startup_time_before'].value - params.adjustment", <1> |
| 94 | + "params" : { |
| 95 | + "adjustment" : 10 <2> |
| 96 | + } |
| 97 | + } |
| 98 | + }, |
| 99 | + "b": { |
| 100 | + "field": "startup_time_after" <3> |
| 101 | + }, |
| 102 | + "type": "paired" |
| 103 | + } |
| 104 | + } |
| 105 | + } |
| 106 | +} |
| 107 | +-------------------------------------------------- |
| 108 | +// TEST[setup:node_upgrade] |
| 109 | + |
| 110 | +<1> The `field` parameter is replaced with a `script` parameter, which uses the |
| 111 | +script to generate values which percentiles are calculated on |
| 112 | +<2> Scripting supports parameterized input just like any other script |
| 113 | +<3> We can mix scripts and fields |
| 114 | + |
0 commit comments