次のファイルがあります。
Time Flag
0.65 5.885581e-01
0.56 5.847484e-01
0.58 5.278409e-01
0.57 1.140746e+00
1.00 0
0.00 0
1.00 1
0.00 0
しかし、それは私が書くときに何かを変えるのを忘れてしまったからです。したがって、タイミングの半分はフラグ列で終わり、フラグの半分は時間列で終わる。やらなければならなかった
Time Flag
0.65 1
0.59 0
0.56 0
0.58 0
0.58 1
0.53 1
0.57 0
1.14 0
したがって、この小さな例では、最初の4行が最初の列になるはずです。最後の4行は2番目の列にする必要があります。各列の要素の半分は、元のファイルで正しい形式(交互)で指定されています。形を変えて型を変える最も簡単な方法は何ですか?
答え1
$ awk 'NR > 1 { d[++n] = $1; d[++n] = $2 } END { print "Time", "Flag"; for (i = 1; 2*i <= n; ++i) printf "%.2f%s%d%s", d[i], OFS, d[n/2 + i], ORS }' file
Time Flag
0.65 1
0.59 0
0.56 0
0.58 0
0.58 1
0.53 1
0.57 0
1.14 0
このawk
コードは、すべてのデータを行単位で読み取り、配列の連続要素として読み取りますd
(ヘッダーをスキップ)。
END
ブロックからヘッダーが印刷され、次に1から配列の長さi
の半分まで繰り返し、d
インデックス(時間値)の値とマーク(フラグ値)i
の値を印刷します。n/2 + i
時間値が小数点以下の2桁の浮動小数点値で印刷され、フラグ値が整数で印刷されるように出力形式を完了します。
OFS
変数にはORS
デフォルトの出力フィールドとレコード区切り文字があります(デフォルトはスペースと改行)。タブ区切り出力の場合awk -v OFS='\t' '{ ... }' file
。
ちなみに、このawk
コードはスタンドアロンスクリプトとして機能します。
#!/usr/bin/awk -f
NR > 1 {
d[++n] = $1
d[++n] = $2
}
END {
print "Time", "Flag"
for (i = 1; 2*i <= n; ++i)
printf "%.2f%s%d%s", d[i], OFS, d[n/2 + i], ORS
}
答え2
OPは、問題がファイルを半分に分割し、各半分を回復して再結合する必要があることを示していませんが、その知識なしにこれを行う方法を知りたいです。
私は本当に好きですcsvkit特にGoCSV宣言的パイプライン処理用。
変換/設定
最初のステップは、固定幅のサンプルデータをCSVに変換することです。 csvkitを使用すると、列の幅パターンを指定できます。
スキーマ.csv
column,start,length
Time,0,4
Flag,7,13
次にCSVに変換します。
in2csv -s schema.csv input.txt > input.csv
分離と転置
入力をフラグと時間というカテゴリ別に分けたい。次に、各カテゴリに対して単一行CSVセットを作成します(次のステップの転置のため)。
gocsv filter -c 2 --regex "^[01]$" input.csv |
gocsv split --max-rows 1 --filename-base flags
補完的な時間には同じパターンが使用されます--exclude
。
gocsv filter -c 2 --regex "^[01]$" --exclude input.csv |
gocsv split --max-rows 1 --filename-base times
これにより、次のファイルセットが作成されます。
ls flags-*.csv
flags-1.csv flags-2.csv flags-3.csv flags-4.csv
それぞれは次のとおりです。
ロゴ-1.csv
Time,Flag
1.00,0
または:
times-4.csv
Time,Flag
0.57,1.140746e+00
ヘッダーはTime,Flag
それほど重要ではありませんが、ヘッダーが存在し、転置された構造に影響を与えるかどうかを見ることが重要です。
各ファイルに対して転置を繰り返し、2番目の列を選択し(誤ったヘッダーが1列目になるため)、適切なヘッダーで終了します。
for FILE in flags-*; do
gocsv transpose $FILE |
gocsv select -c 2 |
gocsv cap --names Flag \
> trans_$FILE;
done
for FILE in times-*; do
gocsv transpose $FILE |
gocsv select -c 2 |
gocsv cap --names Time \
> trans_$FILE;
done
柱に積もった
フラグと時間を独自の列に積み重ねます。
gocsv stack trans_flags* > col_flag.csv
gocsv stack trans_times* > col_time.csv
それから一緒に圧縮します(私はただ使用します)。csvlookもっときれいなMarkdownテーブルがありますが、数値も正規化するからです! ):
gocsv zip col_time.csv col_flag.csv > output.csv
csvlook output.csv
時間 | バナー |
---|---|
0.650… | 1 |
0.589… | 0 |
0.560… | 0 |
0.585… | 0 |
0.580… | 1 |
0.528… | 1 |
0.570… | 0 |
1.141… | 0 |
これはかわいいです。
しかし、最後のステップは、GoCSVに組み込まれた(私にとって新しい)SPRIGテンプレートとround
関数を使用して、浮動小数点、整数、および科学的表記を整理することです。元の列に基づいて新しい列を追加し、新しい列または書式設定された列のみを選択します。
cat output.csv |
gocsv add -n Time -t "{{round .Time 2}}" |
gocsv add -n Flag -t "{{round .Flag 0}}" |
gocsv select -c 3- |
gocsv tsv
私達は次を得ました:
Time Flag
0.65 1
0.59 0
0.56 0
0.58 0
0.58 1
0.53 1
0.57 0
1.14 0