Ruby入門!CSVファイルを読み込んでみよう!
プログラミングにおいては、データの投入やデータの一括変換など、CSVファイルの読み込みや書き込みが求められることが多々あります。
では、RubyでCSVファイルを扱うためにはどんなライブラリや関数が用意されているでしょうか?
今回は、RubyでのCSVファイルの読み込み・書き込み方法をわかりやすく解説していきます。
RubyにおけるCSVファイルの操作(基礎)
Rubyでファイルを開く場合、アクセスモード(読み込み、書き込み、など)、エンコーディング(文字コード)の指定が必要です。また、全体を読み込むのか、行や文字ごとに読み込むのかなどを考慮する必要があります。
ファイルの入出力:read
テキストファイルの内容(=テキストデータ)を全て読み込みたい場合、open
メソッドでファイルを開いた上で、read
メソッドを使うことができます。読み込みが終わったら、close
メソッドでファイルを閉じます。
サンプルコード
f = File.open("sample.txt")
s = f.read # 全て読み込む
f.close
p s
sample.txt
一期一会(いちごいちえ)
一攫千金(いっかくせんきん)
電光石火(でんこうせっか)
悠悠自適(ゆうゆうじてき)
実行結果
一期一会(いちごいちえ)\n一攫千金(いっかくせんきん)\n電光石火(でんこうせっか)\n悠悠自適(ゆうゆうじてき)
サンプルコードでは、最初に「sample.txt」ファイルを開いて(open)内容を全て読み込み(read)、読み込んだデータをp
メソッドを使って表示しています。
標準ライブラリ「csv」
Rubyには、CSV (Comma Separated Values) を扱うライブラリ「csv」が用意されています。
このライブラリには、CSV::Row
クラス、CSV::Table
クラス、CSV::FieldInfo
クラスが含まれています。
では実際に、ライブラリを使用してCSVファイルの読み込み・書き込みを行いましょう。
CSVファイルの読み込み
CSVファイルを読み込んでみましょう。
サンプルコード
require 'csv'
p CSV.read("data.csv")
data.csv
place,minTemp,maxTemp
Okinawa,19,28
Kobe,15,20
Tokyo,17,22
Sapporo,5,12
実行結果
[["place", "minTemp", "maxTemp"], ["Okinawa", "19", "28"], ["Kobe", "15", "20"], ["Tokyo", "17", "22"], ["Sapporo", "5", "12"]]
<解説>
1行目で、「csv」ライブラリを指定します。
2行目で、「csv」ライブラリのread
メソッドで「data.csv」ファイルを読み込み、p
メソッドを使って表示します。
CSVファイルの書き込み
CSVファイルに書き込んでみましょう。
サンプルコード
require 'csv'
CSV.open("sample.csv", "w") do |sample|
sample << ["place", "minTemp", "maxTemp"]
sample << ["Okinawa", "19", "28"]
sample << ["Kobe", "15", "20"]
sample << ["Tokyo", "17", "22"]
sample << ["Sapporo", "5", "12"]
end
sample.csv
place,minTemp,maxTemp
Okinawa,19,28
Kobe,15,20
Tokyo,17,22
Sapporo,5,12
<解説>
1行目で、「csv」ライブラリを指定します。
2行目で、「csv」ライブラリのopen
メソッドで「sample.csv」ファイルを開きます。
3行目~7行目でCSVデータを書き込みます。
RubyにおけるCSVファイルの操作(応用)
RubyではCSVファイルを扱うため非常に便利なメソッドが用意されています。本見出しでは、CSVファイルの操作の応用関数、transpose、hash map、table、headerを解説していきます。
行と列を入れ替えたい:transpose関数
CSVファイルを読み込んだ後、行と列を入れ替えたい、という要望を受けることがあります。例えば次のようなケースです。
このデータは、果物と値段が1行に表示されています
1行目:apple, 700
2行目:banana, 300
3行目:mango, 1200
次のように、果物と値段をそれぞれで一括りにまとめたいという場合です。
[apple, banana, mango][700, 300, 1200]
配列に代入し、希望のフォーマットで出力することもできますが、入れ替えるプログラムを書くのは手間になります。Rubyではこの要望をtranspose
で実現することができます。
サンプルコード
require 'csv'
product1 = CSV.read("sample.csv")
product2 = product1.transpose
p product2
sample.csv
apple, 700
banana, 300
mango, 1200
実行結果
[["apple", "banana", "mango"], [" 700", " 300", " 1200"]]
<解説>
1行目で、「csv」ライブラリを指定します。
2行目で、「csv」ライブラリのread
メソッドで、「sample.csv」ファイルを読み込みます。
3行目で、transpose
メソッドを使用し、行と列を入れ替えます。
4行目で、p
メソッドで出力します。
ハッシュとマップ:hash map関数
Rubyのハッシュでは、キー(key)と値(value)を一つのオブジェクトとして扱います。
例えば、appleは700円、bananaは300円、mangoは1200円というデータの場合、keyは「apple, banana, mango」になり、valueは「700円, 300円, 1200円」になります。
マップとは、配列やハッシュなどの要素の数だけブロック内の処理を繰り返し、結果として作成された配列を返します。「collectメソッド」と表記する場合もあります。
map
メソッドには「汎用性が高い」うえに「記述量を削減する」というメリットがあります。例えば、上記の果物の値段に送料を考慮して一律2倍に値上げしたいという要望があった場合、map
メソッドを使用するとコードをシンプルに記述することができます。
サンプルコード
fruits1 = {"apple": 700, "banana": 300, "mango": 1200}
fruits2 = fruits1.map {|key,val| [key,val * 2]} # valueを2倍する
p fruits2
実行結果
[[:apple, 1400], [:banana, 600], [:mango, 2400]]
<解説>
1行目で、fruits1というハッシュを作成します。
2行目で、ハッシュのvalue値を2倍にします。
3行目で、結果を出力します。
ヘッダー・列・行を一気に取得したい:table/header
通常、CSVファイルはヘッダー部分とデータ部分があります。また、CSVファイル自体table構造となっています。Rubyには、これらのデータ構造に対応する便利なメソッドが用意されています。
では、実際に使ってみましょう。
サンプルコード
require "csv"
table = CSV.table('data.csv')
p table.headers #ヘッダー部を出力
p table[1] #データ部を出力
p table[:place] # 場所の値だけを出力
data.csv
place,minTemp,maxTemp
Okinawa,19,28
Kobe,15,20
Tokyo,17,22
Sapporo,5,12
実行結果
[:place, :mintemp, :maxtemp]
#<CSV::Row place:"Kobe" mintemp:15 maxtemp:20>
["Okinawa", "Kobe", "Tokyo", "Sapporo"]
<解説>
1行目で、「csv」ライブラリを指定します。
2行目で、「csv」ライブラリのtable
メソッドで「data.csv」ファイルを読み込みます。
3行目で、ヘッダー部を出力します。
4行目で、データ部を出力します。
5行目で、縦軸placeを出力します。
CSVファイルの読み込みと書き込み
では、本記事で学んだことをサンプルコードを使って復習しましょう。
本サンプルコードでは、まず果物のCSVファイルデータ「sample1.csv」を読み込みます。値段情報を変更後、CSVファイル「sample2.csv」に書き出します。
サンプルコード
require "csv"
table = CSV.table('sample1.csv') #CSVファイルをテーブルに読み込む
table[:price] = table[:price].map! {|x| [x + 500]} #果物の値段に送料500円をプラスする
p table.headers #ヘッダー部を出力
p table[0] #データ部を出力
File.write('sample2.csv', table) #テーブル情報を出力する
sample1.csv
product, price
apple, 700
banana, 300
mango, 1200
実行結果
#<CSV::Table mode:col_or_row row_count:4>
#<CSV::Row product:"apple" price:[1200]>
sample2.csv
product, price
apple, 1200
banana, 800
mango, 1700
<解説>
1行目で、「csv」ライブラリを指定します。
2行目で、csvライブラリのtable
メソッドで、CSVファイル「sample1.csv」を読み込みます。
3行目で、果物の値段に送料500円をプラスします。
4行目〜5行目で、tableのデータが変更されていることを確認します。
6行目で、値段が変更されたtableデータを、CSVファイル「sample2.csv」として出力します。
まとめ
初期データの投入やデータの一括変換などを行う場合、CSVファイルの読み込みや書き込みは避けては通れません。
Rubyには、CSVファイルを扱うために便利なライブラリや関数が用意されています。これらのライブラリや関数を実践で活用していきましょう!
この記事のキーワードに関する勉強会・イベントを探す
TECH PLAYでは、ITエンジニア向けの勉強会・イベント情報を提供しています。興味のある方はぜひご参加ください。