はじめに
備忘録です。自分用メモといってよい。
前提とするCSV
160Mbくらいで300000行✕27列くらいのCSV
ちなみに、SuperPhoenixとかいう麻雀AIの牌譜分析に作ってたらこうなった。
マイクロソフトが麻雀AIを開発 「天鳳十段の実力」 - ITmedia NEWS
Super Phoenixの論文 - Suphx: Mastering Mahjong with Deep
Reinforcement Learning
ところでCSVを編集するソフトウェアって何使う
蛇足。
どれ使ってもいいけど、大体の感想をば。
使うもの | メリット | デメリット |
---|---|---|
Excel | 見やすい!編集しやすい! | クソ重 |
Googleスプレッドシート | どこでも使える! | 行列合わせて500000セル制限 |
テキストエディタ | ベーシックなテキスト操作、比較的軽い | 見にくいし計算できない |
Python | 色々計算できる。真面目に作るならこれ | デフォルトのcsvパッケージがわかりにくい、環境が必要、内容も閲覧しにくい |
R | 一回読み込めばすごく軽い、グラフ出すのとかすっごい楽、ちょっとした編集もすごい楽 | ちょろっとしたスクリプト組むと意外にも重く使い物にならない |
Powershell | Windowsがあればどこでも、スクリプトできる、比較的軽い | 見やすくはない。だれもお前を愛さない |
本題:PowerShellでCSVを使う
CSVを読み込む
utf8形式でカンマ区切りのCSVを読み込む。とりあえず以下のコマンドを打っておけば、$csvという変数内にPSObject形式で読み込まれる
$csv = Import-CSV .\hogehoge.csv -Delimiter "," -Encoding utf8
パラメータ
- -Delimiter
- 区切り文字。`tとしたりするとタブ区切りも読める
- -Encoding
- 文字コード。PowerShellで一番キレる。もともとのCSVファイルをutf8にしておくことをおすすめする。
かかる時間
たとえば、150MBくらいのファイルをImportしてみたら、6.5秒程度で読み込むことができる。
PS D:\Work\suphx\rspace> Get-ChildItem .\allout_utf8.csv
Directory: D:\Work\suphx\rspace
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2020/12/07 21:55 163871122 allout_utf8.csv
PS D:\Work\suphx\rspace> Measure-Command { Import-Csv .\allout_utf8.csv -Delimiter ',' -Encoding utf8 }
Days : 0
Hours : 0
Minutes : 0
Seconds : 6
Milliseconds : 555
Ticks : 65554450
TotalDays : 7.58732060185185E-05
TotalHours : 0.00182095694444444
TotalMinutes : 0.109257416666667
TotalSeconds : 6.555445
TotalMilliseconds : 6555.445
CSVをファイルに出力する
PSObject形式の配列をパイプでExport-CSVに投げてやるとファイル出力できる。
$csv | Export-CSV .\output.csv -Delimiter "," -Encoding utf8
パラメータ
- -Delimiter
- 区切り文字。`tとしたりするとタブ区切りにもできる
- -Encoding
- 文字コード。PowerShellで一番キレる。utf8はutf8だがなぜかBOM付きutf8。キレそう。
CSV(PSObject)の行の値を表示する
なお、ここからは、もうPSObjectの話なので、正直CSVは関係ない。
$csvは配列で入っているので例えば0を指定すると1行目の値が出力できる。
$csv[0]
CSV(PSObject)の値を変える
直接ぶっこめば良い。PSObjectなのだが、Import-CSVで読み込むとヘッダーがプロパティに当たる。
$csv[0].列名 = "変更後"
なんか色々計算して列として追加する
たとえば、A列とB列をかけたものを列名Xとして追加する。気をつけたいのは、基本的にStringで読み込まれるので数値計算するときは型変換してあげたほうが良い。
下のコマンドで直接$csvの変数のPSObjectにプロパティを加えることができる。
$csv | % {
$tmp = [int]($_.A列) * [int]($_.B列)
$_ | Add-Member -Type NoteProperty -Name "X列" -Value $tmp
}
結論
PowerShellは意外とデータ編集には使えるよ、って話。Windows環境なら環境構築せずとも数分くらいで大容量CSVを編集できるので、楽だよねという感想です。
でも、大容量CSV、というか、大容量テキストファイルを扱うのに、一番取り回しがいいのは、EmEditorなのでぜひ。