0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[備忘録] PowerShell データ変換パイプライン CSV変換

Last updated at Posted at 2025-05-14

PowerShellのパイプラインを活用して、CSVデータの特定列だけを抽出・加工する方法を一気通貫で解説します。

日常業務でよく使うデータ変換テクニックを備忘録としてまとめました。ユースケースを想定して、コマンドを組み合わせデータ変換することにフォーカスしてみました。

powershell-pipeline-svg.png

想定読者

  • 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

image.png

実践!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

image.png

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

image.png

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

image.png

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

image.png

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

image.png

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

image.png

応用例: 在庫管理レポートの作成

最後に、データを分析して在庫管理レポートを作成する例を紹介します。

# 在庫状況の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

image.png

image.png

まとめ

powershell-summary-svg.png

PowerShellのパイプラインとSelect-Objectを活用することで、CSVデータの特定列を効率よく抽出・加工できることが分かりました。実務では、不要な列の除外や必要な情報への絞り込み、列名の変更や計算列の追加といった変換処理、値に応じた条件付きの出力、さらには集計やグループ化によるレポート作成など、さまざまな場面で活用できます。

参考資料


この記事は2025年5月に執筆されました。PowerShellのバージョンやコマンドレットの仕様は、今後のアップデートで変更される可能性があります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?