T-test aggregation

集約された文書から抽出された数値に対して、帰無仮説の下で統計的仮説検定を行う t_test メトリクス集約であり、検定統計量はスチューデントのt分布に従います。実際には、これは2つの母集団の平均の違いが統計的に有意であり、単に偶然によって発生したものではないかを示します。

Syntax

単独での t_test 集約は次のようになります:

Js

  1. {
  2. "t_test": {
  3. "a": "value_before",
  4. "b": "value_after",
  5. "type": "paired"
  6. }
  7. }

アップグレード前後のノードの起動時間の記録があると仮定して、アップグレードがノードの起動時間に意味のある影響を与えたかどうかを確認するためにt検定を見てみましょう。

Python

  1. resp = client.search(
  2. index="node_upgrade",
  3. size=0,
  4. aggs={
  5. "startup_time_ttest": {
  6. "t_test": {
  7. "a": {
  8. "field": "startup_time_before"
  9. },
  10. "b": {
  11. "field": "startup_time_after"
  12. },
  13. "type": "paired"
  14. }
  15. }
  16. },
  17. )
  18. print(resp)

Ruby

  1. response = client.search(
  2. index: 'node_upgrade',
  3. body: {
  4. size: 0,
  5. aggregations: {
  6. startup_time_ttest: {
  7. t_test: {
  8. a: {
  9. field: 'startup_time_before'
  10. },
  11. b: {
  12. field: 'startup_time_after'
  13. },
  14. type: 'paired'
  15. }
  16. }
  17. }
  18. }
  19. )
  20. puts response

Js

  1. const response = await client.search({
  2. index: "node_upgrade",
  3. size: 0,
  4. aggs: {
  5. startup_time_ttest: {
  6. t_test: {
  7. a: {
  8. field: "startup_time_before",
  9. },
  10. b: {
  11. field: "startup_time_after",
  12. },
  13. type: "paired",
  14. },
  15. },
  16. },
  17. });
  18. console.log(response);

Console

  1. GET node_upgrade/_search
  2. {
  3. "size": 0,
  4. "aggs": {
  5. "startup_time_ttest": {
  6. "t_test": {
  7. "a": { "field": "startup_time_before" },
  8. "b": { "field": "startup_time_after" },
  9. "type": "paired"
  10. }
  11. }
  12. }
  13. }
フィールド startup_time_before は数値フィールドでなければなりません。
フィールド startup_time_after は数値フィールドでなければなりません。
同じノードからのデータがあるため、対応のt検定を使用しています。

応答は、検定のp値または確率値を返します。これは、帰無仮説が正しいと仮定した場合に、集約によって処理された結果と同じかそれ以上に極端な結果を得る確率です(つまり、母集団の平均に違いがないことを意味します)。p値が小さいほど、帰無仮説が誤っている可能性が高く、母集団の平均が実際に異なることを示します。

Console-Result

  1. {
  2. ...
  3. "aggregations": {
  4. "startup_time_ttest": {
  5. "value": 0.1914368843365979
  6. }
  7. }
  8. }
p値。

T-Test Types

t_test 集約は、非対応および対応の2サンプルt検定をサポートしています。検定のタイプは、type パラメータを使用して指定できます:

  • "type": "paired"
  • 対応t検定を実行します
  • "type": "homoscedastic"
  • 2サンプル等分散検定を実行します
  • "type": "heteroscedastic"
  • 2サンプル不等分散検定を実行します(これがデフォルトです)

Filters

フィルターを使用して異なるレコードセットで非対応t検定を実行することも可能です。たとえば、2つの異なるノードグループ間でアップグレード前の起動時間の違いをテストしたい場合、グループ名フィールドに対して用語フィルターを使用して、同じフィールド startup_time_before を異なるノードグループで使用します:

Python

  1. resp = client.search(
  2. index="node_upgrade",
  3. size=0,
  4. aggs={
  5. "startup_time_ttest": {
  6. "t_test": {
  7. "a": {
  8. "field": "startup_time_before",
  9. "filter": {
  10. "term": {
  11. "group": "A"
  12. }
  13. }
  14. },
  15. "b": {
  16. "field": "startup_time_before",
  17. "filter": {
  18. "term": {
  19. "group": "B"
  20. }
  21. }
  22. },
  23. "type": "heteroscedastic"
  24. }
  25. }
  26. },
  27. )
  28. print(resp)

Ruby

  1. response = client.search(
  2. index: 'node_upgrade',
  3. body: {
  4. size: 0,
  5. aggregations: {
  6. startup_time_ttest: {
  7. t_test: {
  8. a: {
  9. field: 'startup_time_before',
  10. filter: {
  11. term: {
  12. group: 'A'
  13. }
  14. }
  15. },
  16. b: {
  17. field: 'startup_time_before',
  18. filter: {
  19. term: {
  20. group: 'B'
  21. }
  22. }
  23. },
  24. type: 'heteroscedastic'
  25. }
  26. }
  27. }
  28. }
  29. )
  30. puts response

Js

  1. const response = await client.search({
  2. index: "node_upgrade",
  3. size: 0,
  4. aggs: {
  5. startup_time_ttest: {
  6. t_test: {
  7. a: {
  8. field: "startup_time_before",
  9. filter: {
  10. term: {
  11. group: "A",
  12. },
  13. },
  14. },
  15. b: {
  16. field: "startup_time_before",
  17. filter: {
  18. term: {
  19. group: "B",
  20. },
  21. },
  22. },
  23. type: "heteroscedastic",
  24. },
  25. },
  26. },
  27. });
  28. console.log(response);

Console

  1. GET node_upgrade/_search
  2. {
  3. "size": 0,
  4. "aggs": {
  5. "startup_time_ttest": {
  6. "t_test": {
  7. "a": {
  8. "field": "startup_time_before",
  9. "filter": {
  10. "term": {
  11. "group": "A"
  12. }
  13. }
  14. },
  15. "b": {
  16. "field": "startup_time_before",
  17. "filter": {
  18. "term": {
  19. "group": "B"
  20. }
  21. }
  22. },
  23. "type": "heteroscedastic"
  24. }
  25. }
  26. }
  27. }
フィールド startup_time_before は数値フィールドでなければなりません。
2つのグループを分けるクエリはここで使用できます。
同じフィールドを使用していますが
異なるフィルターを使用しています。
異なるノードからのデータがあるため、対応t検定を使用できません。

Console-Result

  1. {
  2. ...
  3. "aggregations": {
  4. "startup_time_ttest": {
  5. "value": 0.2981858007281437
  6. }
  7. }
  8. }
p値。

母集団は同じインデックスに存在する必要はありません。データセットが異なるインデックスにある場合、_index フィールドに対する用語フィルターを使用して母集団を選択できます。

Script

フィールドによってきれいに表現されていない値に対して t_test を実行する必要がある場合は、ランタイムフィールド で集約を実行してください。たとえば、前の値のロード時間を調整したい場合:

Python

  1. resp = client.search(
  2. index="node_upgrade",
  3. size=0,
  4. runtime_mappings={
  5. "startup_time_before.adjusted": {
  6. "type": "long",
  7. "script": {
  8. "source": "emit(doc['startup_time_before'].value - params.adjustment)",
  9. "params": {
  10. "adjustment": 10
  11. }
  12. }
  13. }
  14. },
  15. aggs={
  16. "startup_time_ttest": {
  17. "t_test": {
  18. "a": {
  19. "field": "startup_time_before.adjusted"
  20. },
  21. "b": {
  22. "field": "startup_time_after"
  23. },
  24. "type": "paired"
  25. }
  26. }
  27. },
  28. )
  29. print(resp)

Ruby

  1. response = client.search(
  2. index: 'node_upgrade',
  3. body: {
  4. size: 0,
  5. runtime_mappings: {
  6. 'startup_time_before.adjusted' => {
  7. type: 'long',
  8. script: {
  9. source: "emit(doc['startup_time_before'].value - params.adjustment)",
  10. params: {
  11. adjustment: 10
  12. }
  13. }
  14. }
  15. },
  16. aggregations: {
  17. startup_time_ttest: {
  18. t_test: {
  19. a: {
  20. field: 'startup_time_before.adjusted'
  21. },
  22. b: {
  23. field: 'startup_time_after'
  24. },
  25. type: 'paired'
  26. }
  27. }
  28. }
  29. }
  30. )
  31. puts response

Js

  1. const response = await client.search({
  2. index: "node_upgrade",
  3. size: 0,
  4. runtime_mappings: {
  5. "startup_time_before.adjusted": {
  6. type: "long",
  7. script: {
  8. source: "emit(doc['startup_time_before'].value - params.adjustment)",
  9. params: {
  10. adjustment: 10,
  11. },
  12. },
  13. },
  14. },
  15. aggs: {
  16. startup_time_ttest: {
  17. t_test: {
  18. a: {
  19. field: "startup_time_before.adjusted",
  20. },
  21. b: {
  22. field: "startup_time_after",
  23. },
  24. type: "paired",
  25. },
  26. },
  27. },
  28. });
  29. console.log(response);

Console

  1. GET node_upgrade/_search
  2. {
  3. "size": 0,
  4. "runtime_mappings": {
  5. "startup_time_before.adjusted": {
  6. "type": "long",
  7. "script": {
  8. "source": "emit(doc['startup_time_before'].value - params.adjustment)",
  9. "params": {
  10. "adjustment": 10
  11. }
  12. }
  13. }
  14. },
  15. "aggs": {
  16. "startup_time_ttest": {
  17. "t_test": {
  18. "a": {
  19. "field": "startup_time_before.adjusted"
  20. },
  21. "b": {
  22. "field": "startup_time_after"
  23. },
  24. "type": "paired"
  25. }
  26. }
  27. }
  28. }