daru_lite 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|