Class: CAFrame::CSVReader

Inherits:
Object
  • Object
show all
Defined in:
lib/carray/frame/csv_parser.rb

Overview

The block reading-control DSL for CAFrame.from_csv. A file often has preamble lines, a units row, or no header at all; the block says, in order, how to consume the stream:

CAFrame.from_csv(path) do skip 3 # drop 3 preamble lines header # next record supplies the column names skip 1 # drop a units row body # the rest are data rows end

CAFrame.from_csv(path) do # headerless file column_names "date", "temp", "rh" body end

The verbs are +skip+ / +header+ / +column_names+ / +body+; each returns a value useful inline (header returns its fields) and the ordering is the script. Without a block, from_csv runs the default +header+ then +body+.

Instance Method Summary collapse

Constructor Details

#initialize(io, sep: ",", quote: '"', strip: false) ⇒ CSVReader

Returns a new instance of CSVReader.



162
163
164
165
166
167
# File 'lib/carray/frame/csv_parser.rb', line 162

def initialize(io, sep: ",", quote: '"', strip: false)
  @io    = io
  @tok   = CSVParser::Tokenizer.new(sep, quote, strip)
  @names = nil
  @rows  = nil
end

Instance Method Details

#bodyObject

Consume the remaining records as data rows.



196
197
198
199
200
201
202
203
# File 'lib/carray/frame/csv_parser.rb', line 196

def body
  rows = []
  while (fields = @tok.read(@io))
    rows << fields
  end
  @rows = rows
  self
end

#column_names(*names) ⇒ Object

Set the column names explicitly (headerless files).



190
191
192
193
# File 'lib/carray/frame/csv_parser.rb', line 190

def column_names(*names)
  @names = names.flatten.map(&:to_s)
  self
end

#header(name = nil) ⇒ Object

Read one record. With no argument it becomes the column names; with a name it is a secondary header (e.g. units) -- read, returned, not used as names. Returns the record's fields either way.



178
179
180
181
182
183
184
185
186
187
# File 'lib/carray/frame/csv_parser.rb', line 178

def header(name = nil)
  fields = @tok.read(@io)
  raise CSVParser::MalformedCSV, "header expected but input ended" if fields.nil?
  if name.nil?
    @names = fields.map(&:to_s)
  else
    (@named_headers ||= {})[name.to_s] = fields
  end
  fields
end

#resultObject

[names_or_nil, rows] for CAFrame.from_csv to build from. names is nil when neither header nor column_names ran (positional names are generated).



207
208
209
# File 'lib/carray/frame/csv_parser.rb', line 207

def result
  [@names, @rows || []]
end

#skip(n = 1) ⇒ Object

Drop +n+ raw lines (preamble, units, notes).



170
171
172
173
# File 'lib/carray/frame/csv_parser.rb', line 170

def skip(n = 1)
  n.times { @io.gets }
  self
end