次の列を含むcsvファイルがあるとします。
timestamp,cpu,memory
実際のデータ型の例は次のとおりです。
このようにデータを可視化することで、人間の目は、CPU を多用する 4 つのアクティビティがどこから始まり終わるかを簡単に確認できます。
R
理想的には、などを使用せずに標準のUnixコマンドラインツールを使用する簡単な方法は何ですかoctave
?「grep」は、この4つのアクティビティの開始と終了を示すファイルの8行だけを表示します。、「cpu」列に基づいていますか?
明らかに、これは少しあいまいでデータにノイズがありますが、開始/終了に近い8行を提供するソリューションは高く評価されます。
csvファイルから簡単に抜粋したもので、4つのアクティビティが急増した最初のアクティビティのみが表示されます。
10:44:21.310,0,53567488
10:44:22.310,1.56257,53575680
10:44:23.326,0,53854208
10:44:24.325,34.3761,57405440
10:44:25.325,73.43985,61747200
10:44:26.325,3.1251,69459968
10:44:27.325,0,69459968
10:44:28.325,0,69459968
10:44:29.325,65.6271,74756096
10:44:30.325,53.1267,77783040
...
10:50:56.450,35.93865,142700544
10:50:57.450,10.93785,142897152
10:50:58.450,1.56255,142897152
10:50:59.450,0,142897152
10:51:00.450,0,142897152
10:51:01.450,0,142897152
理想的には、次の2行が生成されます。
10:44:24.325,34.3761,57405440
10:50:58.450,1.56255,142897152
10:44:26.325
しかし、その間に数秒間CPUアクティビティがないので、10:44:28.325
答えはそれほど賢く、データを「スムーズに」するようなことをしないと思います。したがって、上記のcsvフラグメントが次の4つの行を生成すれば十分です。
10:44:24.325,34.3761,57405440
10:44:26.325,3.1251,69459968
10:44:29.325,65.6271,74756096
10:50:58.450,1.56255,142897152
答え1
1つの方法は、awk
しきい値に達する最初の行とその下の最後の行を取得するようにしきい値を設定することです。次のように動作します。
awk -F, -vthreshold_up=20 -vthreshold_down=10 'BEGIN {
cur = "gt";
}
{
if (cur == "gt" && $2 > threshold_up) {
print;
cur = "lt";
} else if (cur = "lt" && $2 < threshold_down) {
print;
cur = "gt";
}
}' file.csv
答え2
jordanmのアプローチを拡張することで、統計に頼らずに驚くほど強力な機能を構築することができました。残念ながら、スクリプトは少し長くなっていますが、これが完了したので、必要に応じて使用できます。正しいパラメータだけを調べてください。
私は12の実際のデータファイルをテストしましたが、いくつかは次のように汚れていました。
ここでの秘訣は、MIN_DURATION
一時的な急増を無視し、指定された行数まで低下するのに役立つ変数を使用することです。
使用法:
grep-begin-end FIELD_SEPARATOR FIELD_INDEX THRESHOLD_UP THRESHOLD_DOWN MIN_DURATION ...
例:
grep-begin-end , 2 30 4 5 file.csv
grep 開始終了
FIELD_SEPARATOR=$1
FIELD_INDEX=$2
THRESHOLD_UP=$3
THRESHOLD_DOWN=$4
MIN_DURATION=$5
shift 5
awk -F$FIELD_SEPARATOR -vthreshold_up=$THRESHOLD_UP -vthreshold_down=$THRESHOLD_DOWN 'BEGIN {
cur = "gt";
}
{
val = $'$FIELD_INDEX';
# strip of double quotes and convert to number
if (substr(val, 1, 1) == "\"") { val = 0 + substr(val, 2, length(val) - 3); } else { val = 0 + val; }
buf = "";
if (cur == "gt")
{
if (val >= threshold_up)
{
if (buf == "")
buf = $0;
if (duration >= '$MIN_DURATION')
{
print buf;
cur = "lt";
duration = 0;
buf = "";
}
else
{
duration++;
}
}
else
{
duration = 0;
}
}
else if (cur == "lt")
{
if (val <= threshold_down)
{
if (buf == "")
buf = $0;
if (duration >= '$MIN_DURATION')
{
print buf;
cur = "gt";
duration = 0;
buf = "";
}
else
{
duration++;
}
}
else
{
duration = 0;
}
}
}' "$@"
答え3
現在の値が以前の値とN以上異なる場合は、それを印刷する小さなスクリプトを書くことができるようです。データが非常に不連続であるように見え、測定ごとに変化が生じるため、この方法は機能します。
それはまるで
awk -F, -v thr=100 '{if ($2-last>thr || last-$2>thr){print;} last=$2;}' foo.csv