PowerShellはCSV、JSON、イベントログ、プロセス情報などをオブジェクトとして受け取り、抽出、型変換、集計、並べ替え、出力まで一つのパイプラインで処理できます。ただし「簡単」に見える集計ほど、CSVの数値が文字列のまま、欠損値が0扱い、日付が地域設定で逆転、Format-Table後の値をデータとして再利用するといった誤りが起きます。分析前に列定義と検算値を決めます。
安全な流れは、原本を読み取り専用で保持し、小さなサンプルをImport-Csvし、Get-Memberで型を確認し、検証済み行だけを型付きカスタムオブジェクトへ変換してからGroup-ObjectやMeasure-Objectを使う方法です。最終CSVは別名へ書き、行数・合計・欠損件数を元データと照合します。
分析目的と列の意味を先に固定する
売上CSVを例にすると、注文日、部門、数量、単価、金額、通貨、キャンセル状態のどれを集計するかを定義します。「売上」は税込か税抜か、返品を負数で含むか、重複注文を除くかで結果が変わります。PowerShellを書く前に一行一レコードの意味、主キー、単位、タイムゾーン、欠損の扱い、期待する行数をデータ提供者と確認します。
- 一行が注文・明細・顧客のどれを表すか
- 金額の通貨と税込・税抜の区分
- 日付形式とタイムゾーン
- 空欄・0・負数・重複の意味
- 期待する総行数と既知の合計値
元CSVをExcelで開いて上書き保存すると区切り文字、先頭0、日付表現が変わることがあります。原本のハッシュとサイズを記録し、分析用copyを別フォルダーへ置きます。
Import-Csv後の型を明示的に変換する
Import-Csvはヘッダーをプロパティ名にしたカスタムオブジェクトを返しますが、各値は基本的に文字列です。そのため文字列の’100’と’20’をSort-Objectすると数値順にならず、足し算も意図しない結果になります。TryParseを使って日付、整数、小数へ変換し、失敗した行は捨てずにエラー一覧へ分けます。区切り文字とエンコーディングも提供元仕様へ合わせます。
- Get-Memberで入力オブジェクトの型を確認する
- 必須ヘッダーの存在を検証する
- 数値はDecimalまたはInt32へ変換する
- 日付は指定形式とCultureで解析する
- 変換失敗行と理由を別コレクションへ残す
金額へdoubleを無条件に使うと二進浮動小数の丸め差が出ます。通貨の規則に応じてDecimalまたは最小通貨単位の整数を使い、丸め時点と方式を明記します。
CSVを壊さず段階的に集計する例
入力の列と件数を確認
$raw = Import-Csv -LiteralPath '.\sales.csv'
$raw.Count
$raw | Select-Object -First 3
$raw | Get-Member
最初の数行に個人情報がある場合は安全なfixtureへ置き換えます。Import-Csv後のプロパティ値がStringであることを確認します。
数値変換できる行を分ける
$valid = foreach ($row in $raw) {
[decimal]$amount = 0
if ([decimal]::TryParse($row.Amount,[ref]$amount)) {
[pscustomobject]@{ Department=$row.Department; Amount=$amount }
}
}
実運用では失敗行も行番号と理由付きで別一覧へ残します。Culture依存の小数点や桁区切りは入力仕様で固定します。
部門別の件数と合計を計算
$valid | Group-Object Department | ForEach-Object {
$m = $_.Group | Measure-Object Amount -Sum -Average
[pscustomobject]@{Department=$_.Name; Count=$m.Count; Sum=$m.Sum; Average=$m.Average}
}
グループ別Sumの合計が全体Sumと一致するかを別計算で検算します。
元ファイルの識別情報を残す
Get-FileHash -LiteralPath '.\sales.csv' -Algorithm SHA256
$PSVersionTable.PSVersion
ハッシュは内容の識別に使い、真正性を単独で保証する電子署名とは区別します。
抽出・グループ化・集計を段階ごとに検算する
Where-Objectで対象期間や状態を絞り、Group-Objectで部門別などのグループを作り、Measure-ObjectでSum、Average、Minimum、Maximumを求められます。一本の長いパイプラインにすると途中件数を失うため、raw、valid、filtered、summaryの変数へ段階を分けます。各段階でCountと金額合計を記録し、除外された理由別件数も集計します。平均値は件数0のグループや重み付けの有無を確認します。
- 入力・有効・除外・対象期間の件数を記録する
- Group-ObjectのNameが期待カテゴリだけか確認する
- Measure-ObjectのCountとSumを同時に読む
- 平均単価と加重平均を区別する
- 総計とグループ別合計の再合計を一致させる
Group-Object -AsHashTableは参照表作成に便利ですが、キー重複や大文字小文字の扱いを設計します。ハッシュテーブルをパイプへ渡すと一つのオブジェクトとして扱われる点にも注意します。
表示・保存・再利用を混同しない
Format-TableやFormat-Listは画面表示を整えるためのコマンドで、出力オブジェクトを分析用データとして保持するものではありません。選択や計算はSelect-Objectで行い、最終表示の直前だけFormat系を使います。CSVへ保存する場合はExport-Csvへ型付きオブジェクトを渡し、出力先、区切り文字、エンコーディング、NoTypeInformation相当の版差を確認します。既存レポートへ直接追記せず、日付付きの新規ファイルにします。
- Format系はパイプラインの最後に置く
- 列順と列名はSelect-Objectで固定する
- 出力ファイルは原本と別の場所・名前にする
- Export後にImport-Csvして行数とヘッダーを再確認する
- 画面の丸め表示と内部値を区別する
個人情報を含む行をデバッグ目的でFormat-List *へ出すと過剰な列が表示されます。必要な列だけを選び、顧客IDやメールはマスクしたテストデータで開発します。
再現可能な分析として残す
実行日時、PowerShell版、入力ファイルのハッシュ、パラメーター、除外規則、スクリプト版、出力ハッシュを記録すると、同じ結果を再現できます。処理速度が必要でもForEach-Objectから並列化へ急がず、正しい小規模fixtureと期待結果のテストを作ります。大規模CSVではImport-Csvが全件をオブジェクト化するコストを測り、必要ならデータベースや専用分析基盤へ移します。
- Get-FileHashで入力を識別する
- $PSVersionTableで実行環境を記録する
- パラメーターとフィルター期間をログに残す
- 既知の10行fixtureで期待集計をテストする
- データ量と処理時間・メモリを測定する
分析結果は計算が再現できても、元データの品質が悪ければ正しくありません。欠損、重複、範囲外、将来日付、カテゴリ表記揺れを品質レポートとして結果と一緒に示します。
原本・個人情報・数式注入を守る
分析スクリプトは原本を上書きせず、読み取りと出力のディレクトリを分けます。CSVをExcelで開く可能性がある場合、外部入力が数式として解釈される先頭文字を含まないか確認し、出力先の利用方法に合う無害化を設計します。Invoke-Expressionで入力値を式として評価したり、列名から任意のPowerShellを組み立てたりしません。ログには行全体を吐かず、行番号、検証結果、匿名化IDだけを残します。
- Import-Csvの数値列を文字列のまま並べ替えない
- 欠損や変換失敗を黙って0へ置換しない
- Format-Tableの後へExport-Csvをつながない
- 原本CSVへ直接Export-Csvや追記をしない
- 外部データをInvoke-Expressionで計算しない
集計を共有する前の検算
入力件数は、有効件数、除外件数、エラー件数の合計と一致させます。グループ別件数と合計を再集計し、全体値と一致するか確認します。既知の小さなfixtureでは手計算とPowerShell結果を比べ、境界日付、負数、0、空欄、重複、小数、異なるカテゴリ表記を含めます。出力CSVを再Importし、列名、行数、桁、日付、エンコーディングを確認します。
- 列定義・型・単位・欠損規則を文書化した
- 全入力行を有効・除外・エラーへ説明可能に分類した
- グループ別再合計と全体集計が一致した
- 別名出力を再読込し同じ行数と値を確認した
PowerShellが適する分析規模
数千から数十万行程度の運用CSVを定型整形し、Windows管理データと組み合わせる用途ではPowerShellが扱いやすい選択です。複雑な統計、巨大データ、複数人の探索、厳格なスキーマ・履歴・権限制御が必要ならSQL、Python、R、BI基盤を選びます。どの道具でも、列定義と検算値、再現可能な入力識別は共通の品質条件です。

コメント