class Pulo::Frame

Attributes

column_count[R]
column_names[R]
columns[R]
row_count[R]
rows[R]

Public Class Methods

new() click to toggle source
# File lib/pulo/frames/frame.rb, line 13
def initialize
  @rows=[]
  @columns=[]
  @column_names={}
  @column_count=0
  @row_count=0
end

Public Instance Methods

[](column) click to toggle source
# File lib/pulo/frames/frame.rb, line 231
def [](column)
  if column.is_a?(Integer)
    raise IndexError,"No column number #{column} defined." unless @columns[column]
    @columns[column]
  else
    column_no=@column_names[column]
    raise IndexError,"Column with name '#{column}' not found." unless column_no
    @columns[column_no]
  end
end
append_column(name,hidden=false,&formula) click to toggle source
# File lib/pulo/frames/frame.rb, line 168
def append_column(name,hidden=false,&formula)
  col=FrameColumn.new(name,self, hidden, &formula)

  @columns << col
  @column_names.merge!({name=>@column_count})

  @rows.each do |rw|
    cell=FrameCell.new(col,rw)
    col.append_row(cell)
    rw.append_column(cell)
  end
  @column_count+=1
  col
end
append_row(values) click to toggle source
# File lib/pulo/frames/frame.rb, line 183
def append_row(values)
  if values.is_a?(Array)
    vals=values.each
    row=FrameRow.new(self,@row_count)
    @columns.each do |col|
      if values.length==column_count
        v = vals.next
      else
        v = col.value_column? ? vals.next : nil
      end
      cell=FrameCell.new(col,row,v)
      col.append_row(cell)
      row.append_column(cell)
    end
    @rows<<row
    @row_count+=1
    row
  else
    raise 'Expecting an array of values as the append row.'
  end
end
clone() click to toggle source
# File lib/pulo/frames/frame.rb, line 125
def clone
  frame=copy_definition
  @rows.each do |row|
      frame.append_row row.to_a
  end
  frame
end
copy_definition() click to toggle source
# File lib/pulo/frames/frame.rb, line 133
def copy_definition
  frame=Frame.new
  @columns.each do |col|
    frame.append_column(col.name,col.hidden?,&col.formula)
  end
  frame
end
delete_column(name_or_index) click to toggle source
# File lib/pulo/frames/frame.rb, line 141
def delete_column(name_or_index)
  if name_or_index.is_a?(Integer)
    raise IndexError,"No column number #{name_or_index} defined." unless @columns[name_or_index]
    index=name_or_index
    name=@columns[index].name
  else
    index=@column_names[name_or_index]
    raise IndexError,"Column with name '#{name_or_index}' not found." unless index
    name=name_or_index
  end
  @rows.each {|row| row.delete_column(index)}
  @column_names.delete(name)
  @column_names.each do |item|
    @column_names[item[0]]-=1 if @column_names[item[0]]>=index
  end
  @columns.delete_at(index)
  @column_count-=1
end
export_csv(path) click to toggle source
# File lib/pulo/frames/frame.rb, line 21
def export_csv(path)

  CSV.open(path, 'wb') do |csv|
    csv << @columns.map {|col| col.name}
    csv << @columns.map {|col|
      if col.column_class.respond_to?(:quantity_name)
        col.column_class.quantity_name
      else
        col.column_class.name
      end
    }
    csv << @columns.map {|col|
      if col.column_class.respond_to?(:quantity_name)
        col.column_unit.abbreviation
      else
        ''
      end
    }
    @rows.each do |row|
      csv<<row.to_a.map{|cell|
        if cell.class.respond_to?(:quantity_name)
          cell.value
        else
          cell
        end
      }
    end
  end
end
first_row() click to toggle source
# File lib/pulo/frames/frame.rb, line 242
def first_row
  @rows.first
end
formula_columns() click to toggle source
# File lib/pulo/frames/frame.rb, line 284
def formula_columns
  @columns.find_all { |col| !col.value_column?}
end
group(group_function) click to toggle source

applies the given function to each row returns a hash where each element (keyed by the group) is a frame containing the group

# File lib/pulo/frames/frame.rb, line 53
def group(group_function)
  #t=Time.now
  groups={}
  @rows.each do |row|
    res=group_function.call(row)
    if groups[res]
      groups[res].append_row(row.to_a)
    else
      frm=self.copy_definition
      frm.append_row(row.to_a)
      groups.merge!({res=>frm})
    end
  end
  #puts "Groups in #{((Time.now-t)*1000).to_i} ms."
  groups
end
group_reduce(group_function,column_defns) click to toggle source
# File lib/pulo/frames/frame.rb, line 70
def group_reduce(group_function,column_defns)
  #get groups
  groups=group(group_function)

  #t=Time.now
  output=Frame.new
  output.append_column 'Group'

  #setup the columns
  column_defns.keys.each do |col|
    output.append_column(col)
  end

  #add a row to the output for each group produced in the earlier stage
  groups.each do |group|
    row=column_defns.map do |defn|
      if defn[1].class==Proc
        defn[1].call group[1]
      else
        #assume an array with method for descriptive statistics and a column name
        c=group[1][defn[1][1]]
        v=case defn[1][0]
            when :min
              c.to_a.min
            when :max
              c.to_a.max
            else
              DescriptiveStatistics.send(defn[1][0],c.to_a)
          end
        if c.column_class.respond_to?(:quantity_name) && defn[1][0]!=:number
          c.column_class.send(c.column_unit.name,v)
        else
          v
        end
      end
    end
    row.insert 0,group[0]
    output.append_row row
  end
  #puts "Reduce in #{((Time.now-t)*1000).to_i} ms."
  output

end
insert_row(previous_row,values) click to toggle source
# File lib/pulo/frames/frame.rb, line 204
def insert_row(previous_row,values)
  if values.is_a?(Array)
    row_no=previous_row.row_number+1
    vals=values.each
    row=FrameRow.new(self,row_no)
    @columns.each do |col|
      if values.length==column_count
        v = vals.next
      else
        v = col.value_column? ? vals.next : nil
      end
      cell=FrameCell.new(col,row,v)
      col.insert_row(row_no,cell)
      row.append_column(cell)
    end
    @rows.insert(row_no,row)
    @row_count+=1
    @rows.drop(row_no+1).each {|r| r.row_number+=1}
  else
    raise 'Expecting an array of values as the append row.'
  end
end
inspect() click to toggle source
# File lib/pulo/frames/frame.rb, line 276
def inspect
  "Frame Object"
end
last_row() click to toggle source
# File lib/pulo/frames/frame.rb, line 245
def last_row
  @rows.last
end
lookup(value,column) click to toggle source
# File lib/pulo/frames/frame.rb, line 249
def lookup(value,column)
  self[column].lookup(value)
end
recalc_all(with_timing=false) click to toggle source
# File lib/pulo/frames/frame.rb, line 227
def recalc_all(with_timing=false)
  formula_columns.each { |col| col.recalc with_timing }
end
rename_column(old_name,new_name) click to toggle source
# File lib/pulo/frames/frame.rb, line 160
def rename_column(old_name,new_name)
  col=self[old_name]
  col_no=@column_names[old_name]
  @column_names.delete(old_name)
  @column_names.merge!({new_name=>col_no})
  col.name=new_name
end
sort(&sort_function) click to toggle source
# File lib/pulo/frames/frame.rb, line 114
def sort(&sort_function)
  int=@rows.map do |row|
    [row.row_number,sort_function.call(row)]
  end.sort_by {|elm| elm[1]}.map{|elm| elm[0]}
  frm=self.copy_definition
  int.each do |row_no|
    frm.append_row self.rows[row_no].to_a_values
  end
  frm
end
to_s(&filter) click to toggle source
# File lib/pulo/frames/frame.rb, line 253
def to_s(&filter)
  @columns.each {|c| c.recalc_width}
  ret="\n          "
  ret+=@columns.select {|c| !c.hidden?}.map{|s| s.name.ljust(s.width,' ')}.join('  ') + "\n"
  ret+='========= '
  ret+=@columns.select {|c| !c.hidden?}.map{|s| ''.ljust(s.width,'=')}.join('= ') + "\n"
  ret+='          '
  ret+=@columns.select {|c| !c.hidden?}.map{|s|
    if s.column_class.respond_to?(:quantity_name)
      (s.column_class.quantity_name + (s.value_column? ? '' : '*')).ljust(s.width,' ')
    else
      (s.column_class.to_s + (s.value_column? ? '' : '*')).ljust(s.width,' ')
    end
  }.join('  ') + "\n"
  ret+='--------- '
  ret+=@columns.select {|c| !c.hidden?}.map{|s| ''.ljust(s.width,'-')}.join('- ') + "\n"

  ret+=(@rows.select{|row| !block_given? || filter.call(row)}.map { |row| row.to_s}).join("\n")

  ret+="\n" + @rows.length.to_s + " rows\n"
  ret
end
value_columns() click to toggle source
# File lib/pulo/frames/frame.rb, line 280
def value_columns
  @columns.find_all { |col| col.value_column?}
end