「Perlによる巨大CSVファイルの操作について」の版間の差分
imported>Webmaster |
imported>Webmaster |
||
45行目: | 45行目: | ||
}); | }); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | == 注意 == | |
+ | '''フィールド区切り文字'''ですが、よくあるCSVのカラムにカンマが使われている場合があります。その場合、フィールド区切り位置が変わってしまい正しい並び替えが出来なくなりますので、Text::CSV_XSモジュールなどを使ってカラム中の半角カンマを全角に置き換える、またはカンマをカットする等の事前処理を行ってからFile::Sortモジュールを使うようにしましょう。<br /> | ||
---- | ---- | ||
<!-- カテゴリに追加するページ名を記入 --> | <!-- カテゴリに追加するページ名を記入 --> | ||
[[Category:Perl|PerlによるきょだいCSVふぁいるのそうさについて]] | [[Category:Perl|PerlによるきょだいCSVふぁいるのそうさについて]] |
2017年10月27日 (金) 22:53時点における最新版
仕事上、CSVファイルで出力されたデータ整理をしているが。最近ではデータが巨大になりついにEXCELでは処理しきれないデータ量になった。要するに100万行を超えたわけである。しかしながら、データ出力はCSVで出てくるのでなんとかPerlによる巨大CSVファイルの操作が出来るかどうか検討してみた。
巨大CSVファイルの操作
巨大ってどれくらいかというと、大体100万行~1000万行程度のテキストCSVファイルを指しており。操作というのはあるキーを元にしてソート(並び替え)や重複ファイルの削除を考えています。
もっと欲を言えば、1000万行や1億行のデータからある条件でピボットテーブル(クロス集計)で中央値を出したり、平均値を出したり。
条件抽出したり、いろいろなことをPerlをつかってできないかと思っております
データ処理について
本来、このようなデータを処理するにはSQLサーバにデータを入れてSELECTで必要データの抽出などを行えば良いのですが、クライアントでSQLサーバなんかインストール出来ないし(業務用パソコンにソフトのインストールが出来ない設定になっている)、Accessを使えばデータをインポートできるけど並べ替えすらとても遅かったのでちょっと使えないかな、と思っています。
自分の業務ではそこまで手の込んだことは行わないので単純なデータ処理を行い、グラフ化等はEXCELで実施できれば良いと思ってPerlでなんか出来ないかと思い調べて見ました。
File::Sortモジュール
「巨大 CSV Perl」なんてキーワードでググると、配列に代入してソートして・・なんて記事が出てきましたが、肝心なFile::Sortのモジュール記事が全く出てき無かったので、私自身もいろいろなサンプルプログラムを試行錯誤しておりました。
たまたま、File::Sortモジュール記事に目がとまり私が必要としていた機能がワンラインで実現できたので忘れないように記事にしております
File::Sortはファイルの内容を行単位でソートし,別のファイルへ出力する。機能ですか使ってみると以下の機能があることがわかりました
- ある区切りを基準にしてソート(並び替え)をして別のファイルへ出力する
- 複数のファイルをマージして別のファイルへ出力する
- ある区切りを基準にた重複行を削除して別のファイルへ出力する
テストベットで試験をしたら1000万行のソート(並び替え)は90分で完了しました。
3000万行の重複削除では1時間程度で処理が完了しました。これらは時間よりも1000万行~3000万行のCSVデータが扱えた事に感動しました。
結果としてFile::Sortモジュールを使用することで巨大CSVファイルの並び替えやソート操作が可能ということがわかりました。
使い方
File::SortモジュールはCPANでインストールします
(何を言っているのか分からない方は、別サイトでモジュールのインストール方法を見てください)
アルファベット順に並び替え
OPEN等使わないで、直接ファイルを指定してやれば勝手に該当ファイルをオープンして読み取り、出力ファイルに吐き出す。非常に単純明快な使い方。
sort_file({
I => "c:\Input.txt", #入力ファイル名
o => "c:\Output.txt", #出力ファイル名(ソート)
});
重複行を削除する
ある列(ここではフィールド区切り文字でカンマで区切られた1列目を)を基準にして、ソートをして重複行を削除(u=>1)する。(u=>1)が無ければソートするだけ。
#重複ファイルを削除する
sort_file({
t => ",",#フィールド区切り文字
I => "c:\Input.txt", #入力ファイル名
k => 1,#何列目をキーとしてソートをするか?
y => 1000000, # MAX_SORT_RECORDS
u => 1,#重複カット
o => "c:\Output.txt", #出力ファイル名(ソート)
});
注意
フィールド区切り文字ですが、よくあるCSVのカラムにカンマが使われている場合があります。その場合、フィールド区切り位置が変わってしまい正しい並び替えが出来なくなりますので、Text::CSV_XSモジュールなどを使ってカラム中の半角カンマを全角に置き換える、またはカンマをカットする等の事前処理を行ってからFile::Sortモジュールを使うようにしましょう。