PowerShellのパイプラインを活用して、CSVデータの特定列だけを抽出・加工する方法を一気通貫で解説します。
日常業務でよく使うデータ変換テクニックを備忘録としてまとめました。ユースケースを想定して、コマンドを組み合わせデータ変換することにフォーカスしてみました。
想定読者
- PowerShellの基本コマンドを理解している方
- CSV/Excel処理を効率化したい方
- データ変換・加工のテクニックを習得したい方
環境準備
この記事のサンプルはPowerShell 5.1以上で動作確認しています。まずは環境を確認しましょう。
# バージョン確認
$PSVersionTable.PSVersion
# 作業用フォルダを作成(存在しない場合)
$workDir = "C:\Temp\PowerShellCSVDemo"
if (-not (Test-Path $workDir)) {
New-Item -Path $workDir -ItemType Directory
}
Set-Location $workDir
実践!CSV操作パイプライン
STEP 1: サンプルCSVファイルの作成
まずは分析対象のサンプルCSVファイルを作成します。今回は架空の「文房具店の商品データ」を例にします。
# サンプルデータの作成
$csvData = @"
商品ID,商品名,カテゴリ,入荷日,価格,在庫数
P001,カラフルノート,ノート,2023-04-01,320,45
P002,シャープペン0.5mm,筆記具,2023-07-15,350,30
P003,メモ帳A6,ノート,2023-10-01,180,68
P004,蛍光マーカー5色セット,マーカー,2024-01-10,510,25
P005,消しゴム,文房具,2023-05-20,120,80
P006,定規15cm,文房具,2024-04-01,290,35
P007,ボールペン赤,筆記具,2023-09-01,160,55
P008,付箋紙カラフル,事務用品,2023-11-15,390,42
P009,修正テープ,文房具,2024-03-01,280,60
P010,クリップセット,事務用品,2023-06-10,200,75
"@
# CSVファイルとして保存
$csvData | Out-File -FilePath .\stationery_data.csv -Encoding utf8
# 作成したCSVファイルの内容を確認
Write-Host "作成したCSVファイルの内容:" -ForegroundColor Green
Get-Content .\stationery_data.csv
STEP 2: CSVファイルの読み込みと特定列の抽出
CSVファイルを読み込み、必要な列だけを抽出します。
# CSVファイルの読み込み
$products = Import-Csv -Path .\stationery_data.csv
# 特定の列だけを抽出する
Write-Host "`n商品の基本情報だけを抽出する:" -ForegroundColor Green
$products | Select-Object 商品ID, 商品名, カテゴリ | Format-Table
# 条件でフィルタリングする(ノートカテゴリの商品のみ)
Write-Host "`nノートカテゴリの商品だけを抽出する:" -ForegroundColor Green
$products | Where-Object { $_.カテゴリ -eq "ノート" } | Format-Table
STEP 3: 計算列の追加とデータ加工
既存のデータから新しい計算列を作成し、データを加工します。
# 販売価格と在庫金額を計算
Write-Host "`n計算列を追加する:" -ForegroundColor Green
$products |
Select-Object 商品ID, 商品名, 価格,
@{Name = '税込価格'; Expression = { [int]$_.価格 * 1.1 }},
@{Name = '在庫数'; Expression = { [int]$_.在庫数 }},
@{Name = '在庫金額'; Expression = { [int]$_.価格 * [int]$_.在庫数 }} |
Format-Table
# 列名を変更する(日本語→英語)
Write-Host "`n列名を変更する:" -ForegroundColor Green
$products |
Select-Object @{Name = 'ProductID'; Expression = { $_.商品ID }},
@{Name = 'ProductName'; Expression = { $_.商品名 }},
@{Name = 'Category'; Expression = { $_.カテゴリ }},
@{Name = 'Price'; Expression = { $_.価格 }} |
Format-Table
STEP 4: データの並べ替えとグループ化
データを特定の列で並べ替えたり、グループ化して集計したりします。
# 価格の高い順に並べ替え
Write-Host "`n価格の高い順に並べ替え:" -ForegroundColor Green
$products |
Sort-Object -Property { [int]$_.価格 } -Descending |
Select-Object 商品ID, 商品名, カテゴリ, 価格 |
Format-Table
# カテゴリごとに集計
Write-Host "`nカテゴリ別の平均価格と在庫数:" -ForegroundColor Green
$products |
Group-Object -Property カテゴリ |
ForEach-Object {
[PSCustomObject]@{
カテゴリ = $_.Name
商品数 = $_.Count
平均価格 = ($_.Group | Measure-Object -Property 価格 -Average).Average
合計在庫数 = ($_.Group | Measure-Object -Property 在庫数 -Sum).Sum
}
} |
Format-Table
STEP 5: 条件付き書式と高度なデータ変換
値に応じた処理や、日付データの活用方法を紹介します。
# 価格帯に応じて価格帯ランクを設定
Write-Host "`n価格帯ランクの設定:" -ForegroundColor Green
$products |
Select-Object 商品ID, 商品名, 価格,
@{
Name = '価格帯';
Expression = {
$price = [int]$_.価格
switch ($price) {
{ $_ -ge 400 } { 'プレミアム' }
{ $_ -ge 300 -and $_ -lt 400 } { '高価格' }
{ $_ -ge 200 -and $_ -lt 300 } { '中価格' }
default { 'お手頃' }
}
}
} |
Format-Table
# 入荷日から経過日数を計算
Write-Host "`n商品の経過日数計算:" -ForegroundColor Green
$currentDate = Get-Date
$products |
Select-Object 商品ID, 商品名, 入荷日,
@{
Name = '経過日数';
Expression = {
$stockDate = [DateTime]::ParseExact($_.入荷日, "yyyy-MM-dd", $null)
[math]::Floor(($currentDate - $stockDate).TotalDays)
}
} |
Format-Table
STEP 6: 実用的な関数化
これまでの処理を再利用可能な関数にまとめて、実務で活用しやすくします。
# 商品データ分析用の汎用関数
function Convert-ToEnhancedProductData {
param(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[PSCustomObject]$Product,
[Parameter(Mandatory = $false)]
[switch]$IncludePriceAnalysis,
[Parameter(Mandatory = $false)]
[switch]$IncludeStockAge,
[Parameter(Mandatory = $false)]
[decimal]$TaxRate = 0.1
)
process {
# 基本プロパティを設定
$result = [ordered]@{
商品ID = $Product.商品ID
商品名 = $Product.商品名
カテゴリ = $Product.カテゴリ
在庫数 = [int]$Product.在庫数
}
# 価格分析を含める場合
if ($IncludePriceAnalysis) {
$price = [int]$Product.価格
$result['価格'] = $price
$result['税込価格'] = [int]($price * (1 + $TaxRate))
$result['在庫金額'] = $price * [int]$Product.在庫数
# 価格帯を追加
$result['価格帯'] = switch ($price) {
{ $_ -ge 400 } { 'プレミアム' }
{ $_ -ge 300 -and $_ -lt 400 } { '高価格' }
{ $_ -ge 200 -and $_ -lt 300 } { '中価格' }
default { 'お手頃' }
}
}
# 在庫経過日数を含める場合
if ($IncludeStockAge) {
$stockDate = [DateTime]::ParseExact($Product.入荷日, "yyyy-MM-dd", $null)
$currentDate = Get-Date
$result['入荷日'] = $Product.入荷日
$result['経過日数'] = [math]::Floor(($currentDate - $stockDate).TotalDays)
# 在庫ステータスを追加
$result['在庫ステータス'] = switch ([math]::Floor(($currentDate - $stockDate).TotalDays)) {
{ $_ -ge 180 } { '長期在庫' }
{ $_ -ge 90 -and $_ -lt 180 } { '通常在庫' }
default { '新着商品' }
}
}
return [PSCustomObject]$result
}
}
# 関数の使用例:価格分析と在庫経過日数を含めたレポート
Write-Host "`n関数を使った高度な商品分析レポート:" -ForegroundColor Green
$products |
Convert-ToEnhancedProductData -IncludePriceAnalysis -IncludeStockAge |
Format-Table
# 特定カテゴリの商品だけを抽出して処理
Write-Host "`n筆記具カテゴリのみの詳細レポート:" -ForegroundColor Green
$products |
Where-Object { $_.カテゴリ -eq "筆記具" } |
Convert-ToEnhancedProductData -IncludePriceAnalysis |
Format-Table
応用例: 在庫管理レポートの作成
最後に、データを分析して在庫管理レポートを作成する例を紹介します。
# 在庫状況のHTMLレポートを作成
$stockReport = $products |
ForEach-Object {
$stockDate = [DateTime]::ParseExact($_.入荷日, "yyyy-MM-dd", $null)
$currentDate = Get-Date
$daysSinceArrival = [math]::Floor(($currentDate - $stockDate).TotalDays)
$stockStatus = switch ($daysSinceArrival) {
{ $_ -ge 180 } { '長期在庫' }
{ $_ -ge 90 -and $_ -lt 180 } { '通常在庫' }
default { '新着商品' }
}
$inventoryValue = [int]$_.価格 * [int]$_.在庫数
[PSCustomObject]@{
商品ID = $_.商品ID
商品名 = $_.商品名
カテゴリ = $_.カテゴリ
入荷日 = $_.入荷日
経過日数 = $daysSinceArrival
在庫ステータス = $stockStatus
在庫数 = [int]$_.在庫数
在庫金額 = $inventoryValue
}
} |
Sort-Object -Property 在庫ステータス, カテゴリ |
ConvertTo-Html -Title "在庫管理レポート" -PreContent "<h1>文房具店 在庫管理レポート</h1>" -PostContent "<p>生成日時: $(Get-Date)</p>"
$stockReport | Out-File -FilePath .\inventory_report.html -Encoding utf8
Write-Host "`nHTMLレポートを生成しました: $PWD\inventory_report.html" -ForegroundColor Green
# 在庫金額の集計
Write-Host "`n在庫金額の集計:" -ForegroundColor Green
$totalValue = ($products |
ForEach-Object { [int]$_.価格 * [int]$_.在庫数 } |
Measure-Object -Sum).Sum
Write-Host "店舗の総在庫金額: $totalValue 円" -ForegroundColor Yellow
# カテゴリごとの在庫金額の割合
$products |
Group-Object -Property カテゴリ |
ForEach-Object {
$categoryTotal = ($_.Group |
ForEach-Object { [int]$_.価格 * [int]$_.在庫数 } |
Measure-Object -Sum).Sum
[PSCustomObject]@{
カテゴリ = $_.Name
在庫金額 = $categoryTotal
割合 = [math]::Round(($categoryTotal / $totalValue) * 100, 1)
}
} |
Sort-Object -Property 在庫金額 -Descending |
Format-Table
まとめ
PowerShellのパイプラインとSelect-Objectを活用することで、CSVデータの特定列を効率よく抽出・加工できることが分かりました。実務では、不要な列の除外や必要な情報への絞り込み、列名の変更や計算列の追加といった変換処理、値に応じた条件付きの出力、さらには集計やグループ化によるレポート作成など、さまざまな場面で活用できます。
参考資料
この記事は2025年5月に執筆されました。PowerShellのバージョンやコマンドレットの仕様は、今後のアップデートで変更される可能性があります。