daru_lite 0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/ISSUE_TEMPLATE.md +18 -0
- data/.github/workflows/ci.yml +33 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.rubocop.yml +27 -0
- data/.rubocop_todo.yml +137 -0
- data/CONTRIBUTING.md +47 -0
- data/Gemfile +2 -0
- data/History.md +4 -0
- data/LICENSE +24 -0
- data/README.md +218 -0
- data/Rakefile +69 -0
- data/ReleasePolicy.md +20 -0
- data/benchmarks/TradeoffData.csv +65 -0
- data/benchmarks/csv_reading.rb +22 -0
- data/benchmarks/dataframe_creation.rb +39 -0
- data/benchmarks/db_loading.rb +34 -0
- data/benchmarks/duplicating.rb +45 -0
- data/benchmarks/group_by.rb +32 -0
- data/benchmarks/joining.rb +52 -0
- data/benchmarks/row_access.rb +41 -0
- data/benchmarks/row_assign.rb +36 -0
- data/benchmarks/sorting.rb +51 -0
- data/benchmarks/statistics.rb +28 -0
- data/benchmarks/vector_access.rb +31 -0
- data/benchmarks/vector_assign.rb +42 -0
- data/benchmarks/where_clause.rb +48 -0
- data/benchmarks/where_vs_filter.rb +28 -0
- data/daru_lite.gemspec +55 -0
- data/images/README.md +5 -0
- data/images/con0.png +0 -0
- data/images/con1.png +0 -0
- data/images/init0.png +0 -0
- data/images/init1.png +0 -0
- data/images/man0.png +0 -0
- data/images/man1.png +0 -0
- data/images/man2.png +0 -0
- data/images/man3.png +0 -0
- data/images/man4.png +0 -0
- data/images/man5.png +0 -0
- data/images/man6.png +0 -0
- data/lib/daru_lite/accessors/array_wrapper.rb +109 -0
- data/lib/daru_lite/accessors/dataframe_by_row.rb +25 -0
- data/lib/daru_lite/accessors/mdarray_wrapper.rb +7 -0
- data/lib/daru_lite/category.rb +929 -0
- data/lib/daru_lite/configuration.rb +34 -0
- data/lib/daru_lite/core/group_by.rb +403 -0
- data/lib/daru_lite/core/merge.rb +270 -0
- data/lib/daru_lite/core/query.rb +109 -0
- data/lib/daru_lite/dataframe.rb +3080 -0
- data/lib/daru_lite/date_time/index.rb +569 -0
- data/lib/daru_lite/date_time/offsets.rb +397 -0
- data/lib/daru_lite/exceptions.rb +2 -0
- data/lib/daru_lite/extensions/which_dsl.rb +53 -0
- data/lib/daru_lite/formatters/table.rb +52 -0
- data/lib/daru_lite/helpers/array.rb +53 -0
- data/lib/daru_lite/index/categorical_index.rb +201 -0
- data/lib/daru_lite/index/index.rb +374 -0
- data/lib/daru_lite/index/multi_index.rb +374 -0
- data/lib/daru_lite/io/csv/converters.rb +21 -0
- data/lib/daru_lite/io/io.rb +294 -0
- data/lib/daru_lite/io/sql_data_source.rb +97 -0
- data/lib/daru_lite/iruby/helpers.rb +38 -0
- data/lib/daru_lite/iruby/templates/dataframe.html.erb +5 -0
- data/lib/daru_lite/iruby/templates/dataframe_mi.html.erb +5 -0
- data/lib/daru_lite/iruby/templates/dataframe_mi_tbody.html.erb +35 -0
- data/lib/daru_lite/iruby/templates/dataframe_mi_thead.html.erb +21 -0
- data/lib/daru_lite/iruby/templates/dataframe_tbody.html.erb +28 -0
- data/lib/daru_lite/iruby/templates/dataframe_thead.html.erb +21 -0
- data/lib/daru_lite/iruby/templates/multi_index.html.erb +12 -0
- data/lib/daru_lite/iruby/templates/vector.html.erb +5 -0
- data/lib/daru_lite/iruby/templates/vector_mi.html.erb +5 -0
- data/lib/daru_lite/iruby/templates/vector_mi_tbody.html.erb +26 -0
- data/lib/daru_lite/iruby/templates/vector_mi_thead.html.erb +8 -0
- data/lib/daru_lite/iruby/templates/vector_tbody.html.erb +17 -0
- data/lib/daru_lite/iruby/templates/vector_thead.html.erb +8 -0
- data/lib/daru_lite/maths/arithmetic/dataframe.rb +91 -0
- data/lib/daru_lite/maths/arithmetic/vector.rb +117 -0
- data/lib/daru_lite/maths/statistics/dataframe.rb +202 -0
- data/lib/daru_lite/maths/statistics/vector.rb +1019 -0
- data/lib/daru_lite/monkeys.rb +56 -0
- data/lib/daru_lite/vector.rb +1678 -0
- data/lib/daru_lite/version.rb +3 -0
- data/lib/daru_lite.rb +99 -0
- data/profile/_base.rb +23 -0
- data/profile/df_to_a.rb +10 -0
- data/profile/filter.rb +13 -0
- data/profile/joining.rb +13 -0
- data/profile/sorting.rb +12 -0
- data/profile/vector_each_with_index.rb +9 -0
- data/profile/vector_new.rb +9 -0
- data/spec/accessors/array_wrapper_spec.rb +3 -0
- data/spec/category_spec.rb +1741 -0
- data/spec/core/group_by_spec.rb +655 -0
- data/spec/core/merge_spec.rb +179 -0
- data/spec/core/query_spec.rb +347 -0
- data/spec/daru_lite_spec.rb +22 -0
- data/spec/dataframe_spec.rb +4330 -0
- data/spec/date_time/data_spec.rb +197 -0
- data/spec/date_time/date_time_index_helper_spec.rb +72 -0
- data/spec/date_time/index_spec.rb +588 -0
- data/spec/date_time/offsets_spec.rb +465 -0
- data/spec/extensions/which_dsl_spec.rb +38 -0
- data/spec/fixtures/bank2.dat +200 -0
- data/spec/fixtures/boolean_converter_test.csv +5 -0
- data/spec/fixtures/countries.json +7794 -0
- data/spec/fixtures/duplicates.csv +32 -0
- data/spec/fixtures/eciresults.html +394 -0
- data/spec/fixtures/empties.dat +2 -0
- data/spec/fixtures/empty_rows_test.csv +17 -0
- data/spec/fixtures/macau.html +3691 -0
- data/spec/fixtures/macd_data.csv +150 -0
- data/spec/fixtures/matrix_test.csv +100 -0
- data/spec/fixtures/moneycontrol.html +6812 -0
- data/spec/fixtures/music_data.tsv +2501 -0
- data/spec/fixtures/repeated_fields.csv +7 -0
- data/spec/fixtures/sales-funnel.csv +18 -0
- data/spec/fixtures/scientific_notation.csv +4 -0
- data/spec/fixtures/string_converter_test.csv +5 -0
- data/spec/fixtures/strings.dat +2 -0
- data/spec/fixtures/test_xls.xls +0 -0
- data/spec/fixtures/test_xls_2.xls +0 -0
- data/spec/fixtures/url_test.txt~ +0 -0
- data/spec/fixtures/valid_markup.html +62 -0
- data/spec/fixtures/wiki_climate.html +1243 -0
- data/spec/fixtures/wiki_table_info.html +631 -0
- data/spec/formatters/table_formatter_spec.rb +137 -0
- data/spec/helpers_spec.rb +8 -0
- data/spec/index/categorical_index_spec.rb +170 -0
- data/spec/index/index_spec.rb +417 -0
- data/spec/index/multi_index_spec.rb +680 -0
- data/spec/io/io_spec.rb +373 -0
- data/spec/io/sql_data_source_spec.rb +56 -0
- data/spec/iruby/dataframe_spec.rb +170 -0
- data/spec/iruby/helpers_spec.rb +49 -0
- data/spec/iruby/multi_index_spec.rb +37 -0
- data/spec/iruby/vector_spec.rb +105 -0
- data/spec/maths/arithmetic/dataframe_spec.rb +148 -0
- data/spec/maths/arithmetic/vector_spec.rb +165 -0
- data/spec/maths/statistics/dataframe_spec.rb +178 -0
- data/spec/maths/statistics/vector_spec.rb +756 -0
- data/spec/monkeys_spec.rb +42 -0
- data/spec/shared/vector_display_spec.rb +213 -0
- data/spec/spec_helper.rb +87 -0
- data/spec/support/database_helper.rb +30 -0
- data/spec/support/matchers.rb +5 -0
- data/spec/vector_spec.rb +2293 -0
- metadata +571 -0
@@ -0,0 +1,97 @@
|
|
1
|
+
module DaruLite
|
2
|
+
module IO
|
3
|
+
class SqlDataSource
|
4
|
+
# @private
|
5
|
+
class Adapter
|
6
|
+
def initialize(conn, query)
|
7
|
+
@conn = conn
|
8
|
+
@query = query
|
9
|
+
end
|
10
|
+
|
11
|
+
def result_hash
|
12
|
+
column_names
|
13
|
+
.map(&:to_sym)
|
14
|
+
.zip(rows.transpose)
|
15
|
+
.to_h
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Private adapter class for DBI::DatabaseHandle
|
20
|
+
# @private
|
21
|
+
class DbiAdapter < Adapter
|
22
|
+
private
|
23
|
+
|
24
|
+
def column_names
|
25
|
+
result.column_names
|
26
|
+
end
|
27
|
+
|
28
|
+
def rows
|
29
|
+
result.to_a.map(&:to_a)
|
30
|
+
end
|
31
|
+
|
32
|
+
def result
|
33
|
+
@result ||= @conn.execute(@query)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Private adapter class for connections of ActiveRecord
|
38
|
+
# @private
|
39
|
+
class ActiveRecordConnectionAdapter < Adapter
|
40
|
+
private
|
41
|
+
|
42
|
+
def column_names
|
43
|
+
result.columns
|
44
|
+
end
|
45
|
+
|
46
|
+
def rows
|
47
|
+
result.cast_values
|
48
|
+
end
|
49
|
+
|
50
|
+
def result
|
51
|
+
@result ||= @conn.exec_query(@query)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private_constant :DbiAdapter
|
56
|
+
private_constant :ActiveRecordConnectionAdapter
|
57
|
+
|
58
|
+
def self.make_dataframe(db, query)
|
59
|
+
new(db, query).make_dataframe
|
60
|
+
end
|
61
|
+
|
62
|
+
def initialize(db, query)
|
63
|
+
@adapter = init_adapter(db, query)
|
64
|
+
end
|
65
|
+
|
66
|
+
def make_dataframe
|
67
|
+
DaruLite::DataFrame.new(@adapter.result_hash).tap(&:update)
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def init_adapter(db, query)
|
73
|
+
query = String.try_convert(query) or
|
74
|
+
raise ArgumentError, "Query must be a string, #{query.class} received"
|
75
|
+
|
76
|
+
db = attempt_sqlite3_connection(db) if db.is_a?(String) && Pathname(db).exist?
|
77
|
+
|
78
|
+
case db
|
79
|
+
when DBI::DatabaseHandle
|
80
|
+
DbiAdapter.new(db, query)
|
81
|
+
when ActiveRecord::ConnectionAdapters::AbstractAdapter
|
82
|
+
ActiveRecordConnectionAdapter.new(db, query)
|
83
|
+
else
|
84
|
+
raise ArgumentError, "Unknown database adapter type #{db.class}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def attempt_sqlite3_connection(db)
|
89
|
+
DBI.connect("DBI:SQLite3:#{db}")
|
90
|
+
rescue SQLite3::NotADatabaseException
|
91
|
+
raise ArgumentError, "Expected #{db} to point to a SQLite3 database"
|
92
|
+
rescue NameError
|
93
|
+
raise NameError, "In order to establish a connection to #{db}, please require 'dbi'"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module DaruLite
|
2
|
+
# @private
|
3
|
+
module IRuby
|
4
|
+
module Helpers
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def tuples_with_rowspans(index)
|
8
|
+
index.sparse_tuples.transpose
|
9
|
+
.map { |r| nils_counted(r) }
|
10
|
+
.transpose.map(&:compact)
|
11
|
+
end
|
12
|
+
|
13
|
+
def tuples_with_colspans(index)
|
14
|
+
index.sparse_tuples.transpose
|
15
|
+
.map { |r| nils_counted(r) }
|
16
|
+
.map(&:compact)
|
17
|
+
end
|
18
|
+
|
19
|
+
# It is complicated, but the only algo I could think of.
|
20
|
+
# It does [:a, nil, nil, :b, nil, :c] # =>
|
21
|
+
# [[:a,3], nil, nil, [:b,2], nil, :c]
|
22
|
+
# Needed by tuples_with_colspans/rowspans, which we need for pretty HTML
|
23
|
+
def nils_counted(array)
|
24
|
+
grouped = [[array.first]]
|
25
|
+
array[1..].each do |val|
|
26
|
+
if val
|
27
|
+
grouped << [val]
|
28
|
+
else
|
29
|
+
grouped.last << val
|
30
|
+
end
|
31
|
+
end
|
32
|
+
grouped.flat_map do |items|
|
33
|
+
[[items.first, items.count], *Array.new(items.count - 1)]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<tbody>
|
2
|
+
<% DaruLite::IRuby::Helpers.tuples_with_rowspans(@index).first(threshold).zip(@index.to_a).each do |tuple, index| %>
|
3
|
+
<tr>
|
4
|
+
<% tuple.each do |idx, span| %>
|
5
|
+
<th rowspan="<%= span %>"><%= idx %></th>
|
6
|
+
<% end %>
|
7
|
+
<% row[index].each do |element| %>
|
8
|
+
<td><%= element.to_s %></td>
|
9
|
+
<% end %>
|
10
|
+
</tr>
|
11
|
+
<% end %>
|
12
|
+
|
13
|
+
<% if nrows > threshold %>
|
14
|
+
<tr>
|
15
|
+
<% index.width.times do %>
|
16
|
+
<th>...</th>
|
17
|
+
<% end %>
|
18
|
+
<% @vectors.size.times do %>
|
19
|
+
<td>...</td>
|
20
|
+
<% end %>
|
21
|
+
</tr>
|
22
|
+
|
23
|
+
<% last_index = @index.to_a.last
|
24
|
+
last_row = row[last_index] %>
|
25
|
+
|
26
|
+
<tr>
|
27
|
+
<% last_index.each do |idx| %>
|
28
|
+
<th><%= idx %></td>
|
29
|
+
<% end %>
|
30
|
+
<% last_row.each do |element| %>
|
31
|
+
<td><%= element.to_s %></td>
|
32
|
+
<% end %>
|
33
|
+
</tr>
|
34
|
+
<% end %>
|
35
|
+
</tbody>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<thead>
|
2
|
+
<% if @vectors.is_a? MultiIndex %>
|
3
|
+
<% DaruLite::IRuby::Helpers.tuples_with_colspans(@vectors).each_with_index do |tuple, idx| %>
|
4
|
+
<tr>
|
5
|
+
<% if idx.zero? %>
|
6
|
+
<th colspan="<%= index.width %>" rowspan="<%= @vectors.width %>"></th>
|
7
|
+
<% end %>
|
8
|
+
<% tuple.each do |idx, span| %>
|
9
|
+
<th colspan="<%= span %>"><%= idx %></th>
|
10
|
+
<% end %>
|
11
|
+
</tr>
|
12
|
+
<% end %>
|
13
|
+
<% else %>
|
14
|
+
<tr>
|
15
|
+
<th colspan="<%= index.width %>"></th>
|
16
|
+
<% @vectors.each do |vector| %>
|
17
|
+
<th><%=vector%></th>
|
18
|
+
<% end %>
|
19
|
+
</tr>
|
20
|
+
<% end %>
|
21
|
+
</thead>
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<tbody>
|
2
|
+
<% @index.first(threshold).each_with_index do |index, pos| %>
|
3
|
+
<tr>
|
4
|
+
<td><%= index %></td>
|
5
|
+
<% row.at(pos).each do |element| %>
|
6
|
+
<td><%= element.to_s %></td>
|
7
|
+
<% end %>
|
8
|
+
</tr>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<% if nrows > threshold %>
|
12
|
+
<tr>
|
13
|
+
<% (@vectors.size + 1).times do %>
|
14
|
+
<td>...</td>
|
15
|
+
<% end %>
|
16
|
+
</tr>
|
17
|
+
|
18
|
+
<% last_index = @index.to_a.last
|
19
|
+
last_row = row_at @index.size-1 %>
|
20
|
+
|
21
|
+
<tr>
|
22
|
+
<td><%= last_index %></td>
|
23
|
+
<% last_row.each do |element| %>
|
24
|
+
<td><%= element.to_s %></td>
|
25
|
+
<% end %>
|
26
|
+
</tr>
|
27
|
+
<% end %>
|
28
|
+
</tbody>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<thead>
|
2
|
+
<% if @vectors.is_a? MultiIndex %>
|
3
|
+
<% DaruLite::IRuby::Helpers.tuples_with_colspans(@vectors).each_with_index do |tuple, idx| %>
|
4
|
+
<tr>
|
5
|
+
<% if idx.zero? %>
|
6
|
+
<th rowspan="<%= @vectors.width %>"></th>
|
7
|
+
<% end %>
|
8
|
+
<% tuple.each do |idx, span| %>
|
9
|
+
<th colspan="<%= span %>"><%= idx %></th>
|
10
|
+
<% end %>
|
11
|
+
</tr>
|
12
|
+
<% end %>
|
13
|
+
<% else %>
|
14
|
+
<tr>
|
15
|
+
<th></th>
|
16
|
+
<% @vectors.each do |vector| %>
|
17
|
+
<th><%=vector%></th>
|
18
|
+
<% end %>
|
19
|
+
</tr>
|
20
|
+
<% end %>
|
21
|
+
</thead>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<table>
|
2
|
+
<tr>
|
3
|
+
<th colspan="<%= width %>">DaruLite::MultiIndex(<%= size %>x<%= width %>)</th>
|
4
|
+
</tr>
|
5
|
+
<% DaruLite::IRuby::Helpers.tuples_with_rowspans(self).each do |row| %>
|
6
|
+
<tr>
|
7
|
+
<% row.each do |val, span| %>
|
8
|
+
<th rowspan="<%= span %>"><%= val %></th>
|
9
|
+
<% end %>
|
10
|
+
</tr>
|
11
|
+
<% end %>
|
12
|
+
</table>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<tbody>
|
2
|
+
<% DaruLite::IRuby::Helpers.tuples_with_rowspans(@index).first(threshold).zip(to_a).each do |tuple, value| %>
|
3
|
+
<tr>
|
4
|
+
<% tuple.each do |idx, span| %>
|
5
|
+
<th rowspan="<%= span %>"><%= idx %></th>
|
6
|
+
<% end %>
|
7
|
+
<td><%= value %></td>
|
8
|
+
</tr>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<% if size > threshold %>
|
12
|
+
<% last_index = @index.to_a.last %>
|
13
|
+
<tr>
|
14
|
+
<% last_index.size.times do %>
|
15
|
+
<th>...</th>
|
16
|
+
<% end %>
|
17
|
+
<td>...</td>
|
18
|
+
</tr>
|
19
|
+
<tr>
|
20
|
+
<% last_index.each do |idx| %>
|
21
|
+
<th><%= idx %></td>
|
22
|
+
<% end %>
|
23
|
+
<td><%= self[last_index] %></td>
|
24
|
+
</tr>
|
25
|
+
<% end %>
|
26
|
+
</tbody>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<tbody>
|
2
|
+
<% @index.each_with_index.first(threshold).each do |index, pos| %>
|
3
|
+
<tr>
|
4
|
+
<td><%= index %></td>
|
5
|
+
<td><%= self.at(pos) %></td>
|
6
|
+
</tr>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<% if size > threshold %>
|
10
|
+
<% last_index = @index.size-1 %>
|
11
|
+
<tr><td>...</td><td>...</td></tr>
|
12
|
+
<tr>
|
13
|
+
<td><%= last_index %></td>
|
14
|
+
<td><%= self.at last_index %></td>
|
15
|
+
</tr>
|
16
|
+
<% end %>
|
17
|
+
</tbody>
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module DaruLite
|
2
|
+
module Maths
|
3
|
+
# Module encapsulating all aritmetic methods on DataFrame.
|
4
|
+
module Arithmetic
|
5
|
+
module DataFrame
|
6
|
+
# Add a scalar or another DataFrame
|
7
|
+
def +(other)
|
8
|
+
binary_operation :+, other
|
9
|
+
end
|
10
|
+
|
11
|
+
# Subtract a scalar or another DataFrame.
|
12
|
+
def -(other)
|
13
|
+
binary_operation :-, other
|
14
|
+
end
|
15
|
+
|
16
|
+
# Multiply a scalar or another DataFrame.
|
17
|
+
def *(other)
|
18
|
+
binary_operation :*, other
|
19
|
+
end
|
20
|
+
|
21
|
+
# Divide a scalar or another DataFrame.
|
22
|
+
def /(other)
|
23
|
+
binary_operation :/, other
|
24
|
+
end
|
25
|
+
|
26
|
+
# Modulus with a scalar or another DataFrame.
|
27
|
+
def %(other)
|
28
|
+
binary_operation :%, other
|
29
|
+
end
|
30
|
+
|
31
|
+
# Exponent with a scalar or another DataFrame.
|
32
|
+
def **(other)
|
33
|
+
binary_operation :**, other
|
34
|
+
end
|
35
|
+
|
36
|
+
# Calculate exponenential of all vectors with numeric values.
|
37
|
+
def exp
|
38
|
+
only_numerics(clone: false).recode(&:exp)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Calcuate square root of numeric vectors.
|
42
|
+
def sqrt
|
43
|
+
only_numerics(clone: false).recode(&:sqrt)
|
44
|
+
end
|
45
|
+
|
46
|
+
def round(precision = 0)
|
47
|
+
only_numerics(clone: false).recode { |v| v.round(precision) }
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def binary_operation(operation, other)
|
53
|
+
case other
|
54
|
+
when DaruLite::DataFrame
|
55
|
+
dataframe_binary_operation operation, other
|
56
|
+
else
|
57
|
+
scalar_binary_operation operation, other
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def dataframe_binary_operation(operation, other)
|
62
|
+
all_vectors = (vectors.to_a | other.vectors.to_a).sort
|
63
|
+
all_indexes = (index.to_a | other.index.to_a).sort
|
64
|
+
|
65
|
+
hsh =
|
66
|
+
all_vectors.to_h do |vector_name|
|
67
|
+
vector = dataframe_binary_operation_on_vectors other, vector_name, operation, all_indexes
|
68
|
+
|
69
|
+
[vector_name, vector]
|
70
|
+
end
|
71
|
+
|
72
|
+
DaruLite::DataFrame.new(hsh, index: all_indexes, name: @name, dtype: @dtype)
|
73
|
+
end
|
74
|
+
|
75
|
+
def dataframe_binary_operation_on_vectors(other, name, operation, indexes)
|
76
|
+
if has_vector?(name) && other.has_vector?(name)
|
77
|
+
self[name].send(operation, other[name])
|
78
|
+
else
|
79
|
+
DaruLite::Vector.new([], index: indexes, name: name)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def scalar_binary_operation(operation, other)
|
84
|
+
dup.map_vectors! do |vector|
|
85
|
+
vector.numeric? ? vector.send(operation, other) : vector
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
module DaruLite
|
2
|
+
module Maths
|
3
|
+
module Arithmetic
|
4
|
+
module Vector
|
5
|
+
def +(other)
|
6
|
+
binary_op :+, other
|
7
|
+
end
|
8
|
+
|
9
|
+
def -(other)
|
10
|
+
binary_op :-, other
|
11
|
+
end
|
12
|
+
|
13
|
+
def *(other)
|
14
|
+
binary_op :*, other
|
15
|
+
end
|
16
|
+
|
17
|
+
def /(other)
|
18
|
+
binary_op :/, other
|
19
|
+
end
|
20
|
+
|
21
|
+
def %(other)
|
22
|
+
binary_op :%, other
|
23
|
+
end
|
24
|
+
|
25
|
+
def **(other)
|
26
|
+
binary_op :**, other
|
27
|
+
end
|
28
|
+
|
29
|
+
def exp
|
30
|
+
math_unary_op :exp
|
31
|
+
end
|
32
|
+
|
33
|
+
def sqrt
|
34
|
+
math_unary_op :sqrt
|
35
|
+
end
|
36
|
+
|
37
|
+
def abs
|
38
|
+
recode { |e| e&.abs }
|
39
|
+
end
|
40
|
+
|
41
|
+
def round(precision = 0)
|
42
|
+
recode { |e| e&.round(precision) }
|
43
|
+
end
|
44
|
+
|
45
|
+
# Add specified vector.
|
46
|
+
#
|
47
|
+
# @param other [DaruLite::Vector] The vector thats added to this.
|
48
|
+
# @param opts [Boolean] :skipnil if true treats nils as 0.
|
49
|
+
#
|
50
|
+
# @example
|
51
|
+
#
|
52
|
+
# v0 = DaruLite::Vector.new [1, 2, nil, nil]
|
53
|
+
# v1 = DaruLite::Vector.new [2, 1, 3, nil]
|
54
|
+
#
|
55
|
+
# irb> v0.add v1
|
56
|
+
# => #<DaruLite::Vector(4)>
|
57
|
+
# 0 3
|
58
|
+
# 1 3
|
59
|
+
# 2 nil
|
60
|
+
# 3 nil
|
61
|
+
#
|
62
|
+
# irb> v0.add v1, skipnil: true
|
63
|
+
# => #<DaruLite::Vector(4)>
|
64
|
+
# 0 3
|
65
|
+
# 1 3
|
66
|
+
# 2 3
|
67
|
+
# 3 0
|
68
|
+
#
|
69
|
+
def add(other, opts = {})
|
70
|
+
v2v_binary :+, other, skipnil: opts.fetch(:skipnil, false)
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def math_unary_op(operation)
|
76
|
+
recode { |e| Math.send(operation, e) unless e.nil? }
|
77
|
+
end
|
78
|
+
|
79
|
+
def binary_op(operation, other)
|
80
|
+
case other
|
81
|
+
when DaruLite::Vector
|
82
|
+
v2v_binary operation, other
|
83
|
+
else
|
84
|
+
v2o_binary operation, other
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def v2o_binary(operation, other)
|
89
|
+
DaruLite::Vector.new map { |e| e&.send(operation, other) },
|
90
|
+
name: @name, index: @index
|
91
|
+
end
|
92
|
+
|
93
|
+
def v2v_binary(operation, other, opts = {})
|
94
|
+
# FIXME: why the sorting?.. - zverok, 2016-05-18
|
95
|
+
index = ArrayHelper.sort_composite_data(@index.to_a | other.index.to_a)
|
96
|
+
|
97
|
+
elements = index.map do |idx|
|
98
|
+
this = self.index.include?(idx) ? self[idx] : nil
|
99
|
+
that = other.index.include?(idx) ? other[idx] : nil
|
100
|
+
this, that = zero_nil_args(this, that, opts.fetch(:skipnil, false))
|
101
|
+
this && that ? this.send(operation, that) : nil
|
102
|
+
end
|
103
|
+
|
104
|
+
DaruLite::Vector.new(elements, name: @name, index: index)
|
105
|
+
end
|
106
|
+
|
107
|
+
def zero_nil_args(this, that, skipnil)
|
108
|
+
if skipnil
|
109
|
+
this = 0 if this.nil?
|
110
|
+
that = 0 if that.nil?
|
111
|
+
end
|
112
|
+
[this, that]
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|