class Charty::TableAdapters::HashAdapter

Attributes

data[R]

Public Class Methods

array?(data) click to toggle source
# File lib/charty/table_adapters/hash_adapter.rb, line 28
def self.array?(data)
  case data
  when Charty::Vector
    true
  # TODO: Use vector adapter to detect them:
  when Array, method(:daru_vector?), method(:narray_vector?), method(:nmatrix_vector?),
       method(:numpy_vector?), method(:pandas_series?)
    true
  else
    false
  end
end
daru_vector?(x) click to toggle source
# File lib/charty/table_adapters/hash_adapter.rb, line 41
def self.daru_vector?(x)
  defined?(Daru::Vector) && x.is_a?(Daru::Vector)
end
narray_vector?(x) click to toggle source
# File lib/charty/table_adapters/hash_adapter.rb, line 45
def self.narray_vector?(x)
  defined?(Numo::NArray) && x.is_a?(Numo::NArray) && x.ndim == 1
end
new(data, columns: nil, index: nil) click to toggle source
# File lib/charty/table_adapters/hash_adapter.rb, line 61
def initialize(data, columns: nil, index: nil)
  case data
  when Hash
    arrays = data.values
    columns ||= data.keys
  when Array
    case data[0]
    when Numeric, String, Time, Date
      arrays = [data]
    when Hash
      columns ||= data.map(&:keys).inject(&:|)
      arrays = columns.map { [] }
      data.each do |record|
        columns.each_with_index do |key, i|
          arrays[i] << record[key]
        end
      end
    when Vector
      arrays = data
    when self.class.method(:array?)
      unsupported_data_format unless data.all?(&self.class.method(:array?))
      arrays = data.map(&:to_a).transpose
    else
      unsupported_data_format
    end
  when ->(x) { defined?(CSV::Table) && x.is_a?(CSV::Table) }
    columns ||= data.headers
    arrays = data.headers.map {|x| data[x] }
  else
    unsupported_data_format
  end

  unless arrays.empty?
    arrays, columns, index = check_data(arrays, columns, index)
  end

  @data = arrays.map.with_index {|a, i| [columns[i], a] }.to_h
  self.columns = columns unless columns.nil?
  self.index = index unless index.nil?
end
nmatrix_vector?(x) click to toggle source
# File lib/charty/table_adapters/hash_adapter.rb, line 49
def self.nmatrix_vector?(x)
  defined?(NMatrix) && x.is_a?(NMatrix) && x.dim == 1
end
numpy_vector?(x) click to toggle source
# File lib/charty/table_adapters/hash_adapter.rb, line 53
def self.numpy_vector?(x)
  defined?(Numpy::NDArray) && x.is_a?(Numpy::NDArray) && x.ndim == 1
end
pandas_series?(x) click to toggle source
# File lib/charty/table_adapters/hash_adapter.rb, line 57
def self.pandas_series?(x)
  defined?(Pandas::Series) && x.is_a?(Pandas::Series)
end
supported?(data) click to toggle source
# File lib/charty/table_adapters/hash_adapter.rb, line 8
def self.supported?(data)
  case data
  when []
    true
  when Array
    case data[0]
    when Numeric, String, Time, Date
      true
    when Hash
      data.all? {|el| el.is_a? Hash }
    when method(:array?)
      data.all?(&method(:array?))
    end
  when Hash
    true
  when ->(x) { defined?(CSV::Table) && x.is_a?(CSV::Table) }
    true
  end
end

Public Instance Methods

[](row, column) click to toggle source
# File lib/charty/table_adapters/hash_adapter.rb, line 176
def [](row, column)
  if row
    @data[column][row]
  else
    case column
    when Array
      slice_data = column.map { |cn|
        [cn, self[nil, cn]]
      }.to_h
      return Charty::Table.new(slice_data, index: self.index)
    when Symbol
      sym_key = column
      str_key = column.to_s
    else
      str_key = String.try_convert(column)
      sym_key = str_key.to_sym
    end

    column_data = if @data.key?(sym_key)
                    @data[sym_key]
                  else
                    @data[str_key]
                  end
    Vector.new(column_data, index: index, name: column)
  end
end
[]=(key, values) click to toggle source
# File lib/charty/table_adapters/hash_adapter.rb, line 203
def []=(key, values)
  case key
  when Symbol
    str_key = key.to_s
    sym_key = key
  else
    str_key = key.to_str
    sym_key = str_key.to_sym
  end

  orig_values = values
  values = Vector.try_convert(values)
  if values.nil?
    raise ArgumentError,
          "`values` must be convertible to Charty::Vector"
  end

  if values.length != self.length
    raise ArgumentError,
          "`values` length does not match the length of the table"
  end

  if @data.key?(sym_key)
    @data[sym_key] = values
  elsif @data.key?(str_key)
    @data[str_key] = values
  elsif key == sym_key
    @data[sym_key] = values
    new_column = sym_key
  else
    @data[str_key] = values
    new_column = sym_key
  end

  if new_column
    self.columns = Index.new([*self.columns, new_column])
  end

  values
end
column_length() click to toggle source
# File lib/charty/table_adapters/hash_adapter.rb, line 163
def column_length
  data.length
end
compare_data_equality(other) click to toggle source
# File lib/charty/table_adapters/hash_adapter.rb, line 167
def compare_data_equality(other)
  case other
  when DaruAdapter, PandasDataFrameAdapter
    other.compare_data_equality(self)
  else
    super
  end
end
each() { |record| ... } click to toggle source
# File lib/charty/table_adapters/hash_adapter.rb, line 244
def each
  i, n = 0, shape[0]
  while i < n
    record = @data.map {|k, v| v[i] }
    yield record
    i += 1
  end
end
length() click to toggle source
# File lib/charty/table_adapters/hash_adapter.rb, line 154
def length
  case
  when column_names.empty?
    0
  else
    data[column_names[0]].size
  end
end
reset_index() click to toggle source
# File lib/charty/table_adapters/hash_adapter.rb, line 253
def reset_index
  index_name = index.name || :index
  Charty::Table.new({ index_name => index.to_a }.merge(data))
end

Private Instance Methods

check_data(arrays, columns, index) click to toggle source
# File lib/charty/table_adapters/hash_adapter.rb, line 102
        def check_data(arrays, columns, index)
  # NOTE: After Ruby 2.7, we can write the following code by filter_map:
  #         indexes = Util.filter_map(arrays) {|ary| ary.index if ary.is_a?(Charty::Vector) }
  indexes = []
  arrays.each do |array|
    index = case array
            when Charty::Vector
              array.index
            when ->(x) { defined?(Daru) && x.is_a?(Daru::Vector) }
              Charty::DaruIndex.new(array.index)
            when ->(x) { defined?(Pandas) && x.is_a?(Pandas::Series) }
              Charty::PandasIndex.new(array.index)
            else
              if index.nil?
                RangeIndex.new(0 ... array.size)
              else
                check_and_convert_index(index, :index, array.size)
              end
            end
    indexes << index
  end
  index = union_indexes(*indexes)

  arrays = arrays.map do |array|
    Vector.try_convert(array)
  end

  columns = generate_column_names(arrays.length, columns)

  arrays.zip(columns) do |array, column|
    array.name = column.to_sym if array.name.to_s != column
  end

  return arrays, columns, index
end
generate_column_names(n_columns, columns) click to toggle source
# File lib/charty/table_adapters/hash_adapter.rb, line 268
        def generate_column_names(n_columns, columns)
  # FIXME: this is the same as NArrayAdapter#generate_column_names
  columns ||= []
  if columns.length >= n_columns
    columns[0, n_columns]
  else
    columns + columns.length.upto(n_columns - 1).map {|i| "X#{i}" }
  end
end
make_data_from_records(data, columns) click to toggle source
# File lib/charty/table_adapters/hash_adapter.rb, line 258
        def make_data_from_records(data, columns)
  n_rows = data.length
  n_columns = data.map(&:size).max
  columns = generate_column_names(n_columns, columns)
  columns.map.with_index { |key, j|
    values = n_rows.times.map {|i| data[i][j] }
    [key, values]
  }.to_h
end
union_indexes(*indexes) click to toggle source
# File lib/charty/table_adapters/hash_adapter.rb, line 138
        def union_indexes(*indexes)
  result = nil
  while result.nil? && indexes.length > 0
    result = indexes.shift
  end
  indexes.each do |index|
    next if index.nil?
    result = result.union(index)
  end
  result
end
unsupported_data_format() click to toggle source
# File lib/charty/table_adapters/hash_adapter.rb, line 278
        def unsupported_data_format
  raise ArgumentError, "Unsupported data format"
end