ボックスプロット集約
集約されたドキュメントから抽出された数値のボックスプロットを計算する boxplot
メトリクス集約です。これらの値は、ドキュメント内の特定の数値または ヒストグラムフィールド から生成されることがあります。
boxplot
集約は、ボックスプロット を作成するために必要な情報を返します:最小値、最大値、中央値、第一四分位数(25パーセンタイル)および第三四分位数(75パーセンタイル)値。
構文
boxplot
集約は、単独で次のようになります:
Js
{
"boxplot": {
"field": "load_time"
}
}
ロード時間を表すボックスプロットを見てみましょう:
Python
resp = client.search(
index="latency",
size=0,
aggs={
"load_time_boxplot": {
"boxplot": {
"field": "load_time"
}
}
},
)
print(resp)
Ruby
response = client.search(
index: 'latency',
body: {
size: 0,
aggregations: {
load_time_boxplot: {
boxplot: {
field: 'load_time'
}
}
}
}
)
puts response
Js
const response = await client.search({
index: "latency",
size: 0,
aggs: {
load_time_boxplot: {
boxplot: {
field: "load_time",
},
},
},
});
console.log(response);
コンソール
GET latency/_search
{
"size": 0,
"aggs": {
"load_time_boxplot": {
"boxplot": {
"field": "load_time"
}
}
}
}
フィールド load_time は数値フィールドでなければなりません |
コンソール-結果
{
...
"aggregations": {
"load_time_boxplot": {
"min": 0.0,
"max": 990.0,
"q1": 167.5,
"q2": 445.0,
"q3": 722.5,
"lower": 0.0,
"upper": 990.0
}
}
}
この場合、下ひげと上ひげの値は最小値と最大値に等しくなります。一般的に、これらの値は 1.5 IQR 範囲であり、つまり `````q1 - (1.5 IQR)と
q3 + (1.5 * IQR)に最も近い値です。これは近似であるため、与えられた値は実際のデータから観測された値ではない可能性がありますが、合理的な誤差範囲内にあるべきです。ボックスプロット集約は外れ値ポイントを直接返しませんが、
lower > minまたは
upper < max````` を確認して、どちら側に外れ値が存在するかを確認し、直接クエリすることができます。
スクリプト
インデックスが正確に作成されていない値のボックスプロットを作成する必要がある場合は、ランタイムフィールド を作成し、そのボックスプロットを取得する必要があります。たとえば、ロード時間がミリ秒単位であるが、秒単位で計算された値が必要な場合は、ランタイムフィールドを使用して変換します:
Python
resp = client.search(
index="latency",
size=0,
runtime_mappings={
"load_time.seconds": {
"type": "long",
"script": {
"source": "emit(doc['load_time'].value / params.timeUnit)",
"params": {
"timeUnit": 1000
}
}
}
},
aggs={
"load_time_boxplot": {
"boxplot": {
"field": "load_time.seconds"
}
}
},
)
print(resp)
Ruby
response = client.search(
index: 'latency',
body: {
size: 0,
runtime_mappings: {
'load_time.seconds' => {
type: 'long',
script: {
source: "emit(doc['load_time'].value / params.timeUnit)",
params: {
"timeUnit": 1000
}
}
}
},
aggregations: {
load_time_boxplot: {
boxplot: {
field: 'load_time.seconds'
}
}
}
}
)
puts response
Js
const response = await client.search({
index: "latency",
size: 0,
runtime_mappings: {
"load_time.seconds": {
type: "long",
script: {
source: "emit(doc['load_time'].value / params.timeUnit)",
params: {
timeUnit: 1000,
},
},
},
},
aggs: {
load_time_boxplot: {
boxplot: {
field: "load_time.seconds",
},
},
},
});
console.log(response);
コンソール
GET latency/_search
{
"size": 0,
"runtime_mappings": {
"load_time.seconds": {
"type": "long",
"script": {
"source": "emit(doc['load_time'].value / params.timeUnit)",
"params": {
"timeUnit": 1000
}
}
}
},
"aggs": {
"load_time_boxplot": {
"boxplot": { "field": "load_time.seconds" }
}
}
}
ボックスプロットの値は(通常)近似値です
boxplot
メトリクスで使用されるアルゴリズムは TDigest と呼ばれています(T-Digestsを使用した正確な分位数の計算でテッド・ダニングによって導入されました)。
ボックスプロットは他のパーセンタイル集約と同様に 非決定的 です。これは、同じデータを使用してわずかに異なる結果を得る可能性があることを意味します。
圧縮
近似アルゴリズムは、メモリの利用と推定精度のバランスを取る必要があります。このバランスは compression
パラメータを使用して制御できます:
Python
resp = client.search(
index="latency",
size=0,
aggs={
"load_time_boxplot": {
"boxplot": {
"field": "load_time",
"compression": 200
}
}
},
)
print(resp)
Ruby
response = client.search(
index: 'latency',
body: {
size: 0,
aggregations: {
load_time_boxplot: {
boxplot: {
field: 'load_time',
compression: 200
}
}
}
}
)
puts response
Js
const response = await client.search({
index: "latency",
size: 0,
aggs: {
load_time_boxplot: {
boxplot: {
field: "load_time",
compression: 200,
},
},
},
});
console.log(response);
コンソール
GET latency/_search
{
"size": 0,
"aggs": {
"load_time_boxplot": {
"boxplot": {
"field": "load_time",
"compression": 200
}
}
}
}
圧縮はメモリ使用量と近似誤差を制御します |
TDigest アルゴリズムは、パーセンタイルを近似するために「ノード」を使用します。ノードが多いほど、精度が高く(データのボリュームに比例して大きなメモリフットプリント)、compression
パラメータは最大ノード数を 20 * compression
に制限します。
したがって、圧縮値を増加させることで、より多くのメモリをコストにしてパーセンタイルの精度を向上させることができます。大きな圧縮値は、基礎となるツリーのデータ構造が大きくなるため、アルゴリズムを遅くします。デフォルトの圧縮値は 100
です。
「ノード」は約 32 バイトのメモリを使用するため、最悪のシナリオ(ソートされて順序通りに到着する大量のデータ)では、デフォルト設定で約 64KB の TDigest が生成されます。実際にはデータはよりランダムであり、TDigest はより少ないメモリを使用します。
実行ヒント
TDigest のデフォルト実装はパフォーマンスの最適化がされており、数百万または数十億のサンプル値にスケーリングしながら、許容可能な精度レベルを維持します(場合によっては数百万のサンプルで相対誤差が 1% に近い)。精度のために最適化された実装を使用するオプションがあり、パラメータ execution_hint
を値 high_accuracy
に設定します:
Python
resp = client.search(
index="latency",
size=0,
aggs={
"load_time_boxplot": {
"boxplot": {
"field": "load_time",
"execution_hint": "high_accuracy"
}
}
},
)
print(resp)
Ruby
response = client.search(
index: 'latency',
body: {
size: 0,
aggregations: {
load_time_boxplot: {
boxplot: {
field: 'load_time',
execution_hint: 'high_accuracy'
}
}
}
}
)
puts response
Js
const response = await client.search({
index: "latency",
size: 0,
aggs: {
load_time_boxplot: {
boxplot: {
field: "load_time",
execution_hint: "high_accuracy",
},
},
},
});
console.log(response);
コンソール
GET latency/_search
{
"size": 0,
"aggs": {
"load_time_boxplot": {
"boxplot": {
"field": "load_time",
"execution_hint": "high_accuracy"
}
}
}
}
精度のために TDigest を最適化し、パフォーマンスを犠牲にします |
このオプションは、精度を向上させる可能性があります(場合によっては数百万のサンプルで相対誤差が 0.01% に近い)が、その場合、パーセンタイルクエリの完了に 2 倍から 10 倍の時間がかかります。
欠損値
missing
パラメータは、値が欠けているドキュメントがどのように扱われるべきかを定義します。デフォルトでは無視されますが、値があるかのように扱うことも可能です。
Python
resp = client.search(
index="latency",
size=0,
aggs={
"grade_boxplot": {
"boxplot": {
"field": "grade",
"missing": 10
}
}
},
)
print(resp)
Ruby
response = client.search(
index: 'latency',
body: {
size: 0,
aggregations: {
grade_boxplot: {
boxplot: {
field: 'grade',
missing: 10
}
}
}
}
)
puts response
Js
const response = await client.search({
index: "latency",
size: 0,
aggs: {
grade_boxplot: {
boxplot: {
field: "grade",
missing: 10,
},
},
},
});
console.log(response);
コンソール
GET latency/_search
{
"size": 0,
"aggs": {
"grade_boxplot": {
"boxplot": {
"field": "grade",
"missing": 10
}
}
}
}
grade フィールドに値がないドキュメントは、値が 10 のドキュメントと同じバケットに入ります。 |