Class: Charty::TableAdapters::HashAdapter

Inherits:
BaseAdapter
  • Object
show all
Defined in:
lib/charty/table_adapters/hash_adapter.rb

Instance Attribute Summary collapse

Attributes inherited from BaseAdapter

#columns, #index

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from BaseAdapter

#==, #column?, #column_names, #drop_na, #group_by, #melt, #sort_values

Constructor Details

#initialize(data, columns: nil, index: nil) ⇒ HashAdapter

Returns a new instance of HashAdapter.



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# 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 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

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



153
154
155
# File 'lib/charty/table_adapters/hash_adapter.rb', line 153

def data
  @data
end

Class Method Details

.array?(data) ⇒ Boolean

Returns:

  • (Boolean)


28
29
30
31
32
33
34
35
36
37
38
39
# 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) ⇒ Boolean

Returns:

  • (Boolean)


41
42
43
# 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) ⇒ Boolean

Returns:

  • (Boolean)


45
46
47
# 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

.nmatrix_vector?(x) ⇒ Boolean

Returns:

  • (Boolean)


49
50
51
# 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) ⇒ Boolean

Returns:

  • (Boolean)


53
54
55
# 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) ⇒ Boolean

Returns:

  • (Boolean)


57
58
59
# 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) ⇒ Boolean

Returns:

  • (Boolean)


8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 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

Instance Method Details

#[](row, column) ⇒ Object



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/charty/table_adapters/hash_adapter.rb', line 179

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
    # FIXME: Here column_data need to be dupped to
    # prevent to overwrite the name of Pandas::Series
    Vector.new(column_data.dup, index: index, name: column)
  end
end

#[]=(key, values) ⇒ Object



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/charty/table_adapters/hash_adapter.rb', line 208

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
  case values
  when Charty::Vector
    values = values.data
  else
    values = Array.try_convert(values)
  end
  if values.nil?
    raise ArgumentError,
          "`values` must be convertible to Array"
  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_lengthObject



166
167
168
# File 'lib/charty/table_adapters/hash_adapter.rb', line 166

def column_length
  data.length
end

#compare_data_equality(other) ⇒ Object



170
171
172
173
174
175
176
177
# File 'lib/charty/table_adapters/hash_adapter.rb', line 170

def compare_data_equality(other)
  case other
  when DaruAdapter, PandasDataFrameAdapter
    other.compare_data_equality(self)
  else
    super
  end
end

#eachObject



254
255
256
257
258
259
260
261
# File 'lib/charty/table_adapters/hash_adapter.rb', line 254

def each
  i, n = 0, shape[0]
  while i < n
    record = @data.map {|k, v| v[i] }
    yield record
    i += 1
  end
end

#lengthObject



157
158
159
160
161
162
163
164
# File 'lib/charty/table_adapters/hash_adapter.rb', line 157

def length
  case
  when column_names.empty?
    0
  else
    data[column_names[0]].size
  end
end

#reset_indexObject



263
264
265
266
# File 'lib/charty/table_adapters/hash_adapter.rb', line 263

def reset_index
  index_name = index.name || :index
  Charty::Table.new({ index_name => index.to_a }.merge(data))
end