Drop the first n rows from daru dataframe - ruby

One can drop the first n elements of an array by using Array#drop.
a = [1,2,3]
a.drop(2) # => [3]
I want to drop the first n rows from a Daru::DataFrame object. It seems this class does not implement such drop method.
How can I delete the first n rows from a Daru::DataFrame object?

You can use row_at to retrieve all the rows without the first 4.
Example:
2.4.5 :001 > require 'daru'
=> true
2.4.5 :002 > df = Daru::DataFrame.new({
2.4.5 :003 > 'col0' => [1,2,3,4,5,6],
2.4.5 :004 > 'col2' => ['a','b','c','d','e','f'],
2.4.5 :005 > 'col1' => [11,22,33,44,55,66]
2.4.5 :006?> })
=> #<Daru::DataFrame(6x3)>
col0 col2 col1
0 1 a 11
1 2 b 22
2 3 c 33
3 4 d 44
4 5 e 55
5 6 f 66
Retrieve rows:
2.4.5 :010 > df.row_at(4..df.shape()[0])
=> #<Daru::DataFrame(2x3)>
col0 col2 col1
4 5 e 55
5 6 f 66

You can put this into a loop:
df.delete_row(0)
https://www.rubydoc.info/gems/daru/0.1.4.1/Daru/DataFrame#delete_row-instance_method

Related

accounting lettering algorithm to find matching amounts

Do you know resources or links who talks about lettering algorithms ?
I need to find positives amounts that matchs with negatives ones to do lettering. For example :
array (
0 =>
array (
'debit' => NULL,
'credit' => '440'
),
1 =>
array (
'debit' => '880',
'credit' => NULL
),
2 =>
array (
'debit' => '440',
'credit' => NULL
),
)
here, indexes 0 and 2 can be associated with index 1, baut i can have more complicated associations
more examples :
DEBIT CREDIT
1 20
2 20
3 40
result => 1 / 2
DEBIT CREDIT
1 20
2 40
3 40
result => 2 / 3
DEBIT CREDIT
1 20
2 20
3 20
4 20
result => 1 / 3
DEBIT CREDIT
1 20
2 20
3 20
4 40
5 20
result => 1-2-5 / 3-4
thanks

Horizontal concat in Daru::DataFrame?

I know that by Daru::DataFrame#concat one can concatenate dataframes, appending the argument df to the bottom of the caller df.
Now I want to achieve what is df.concat(other, axis=1) in Pandas. In other words, given I have two dataframes where the index are the same, append one df to the right of the other df, resulting df having same index but the concatenated vectors.
Is this possible by some method? Or do I need to iterate and add each columns in for loop?
Is this what you are looking for possibly?
data_frame = data_frame.join(jobs_data_frame, how: :left, on: [:user_id])
You can use add_vector method.
For eg:
2.6.3 :001 > require 'daru'
2.6.3 :007 > df = Daru::DataFrame.new([[00,01,02], [10,11,12],[20,21,22]], order: ["a", "b", "c"])
=> #<Daru::DataFrame(3x3)>
a b c
0 0 10 20
1 1 11 21
2 2 12 22
2.6.3 :008 > df.add_vector("d", [30, 31, 32])
=> [30, 31, 32]
2.6.3 :009 > df
=> #<Daru::DataFrame(3x4)>
a b c d
0 0 10 20 30
1 1 11 21 31
2 2 12 22 32
Although you'll have to add each vector separately.

Setting With Enlargement in daru

There is some way to Setting With Enlargement in daru? Something similar to pandas with loc.
Yes you can.
For Daru::Vector objects use the #push method like so:
require 'daru'
v = Daru::Vector.new([1,2,3], index: [:a,:b,:c])
v.push(23, :r)
v
#=>
#<Daru::Vector:74005360 #name = nil #size = 4 >
# nil
# a 1
# b 2
# c 3
# r 23
For setting a new vector in Daru::DataFrame, call the #[]= method with your new name inside the []. You can either assign a Daru::Vector or an Array.
If you assign Daru::Vector, the data will be aligned so that the indexes of the DataFrame and Vector match.
For example,
require 'daru'
df = Daru::DataFrame.new({a: [1,2,3], b: [5,6,7]})
df[:r] = [11,22,33]
df
# =>
#<Daru::DataFrame:73956870 #name = c8a65ffe-217d-43bb-b6f8-50d2530ec053 #size = 3>
# a b r
# 0 1 5 11
# 1 2 6 22
# 2 3 7 33
You assign a row with the DataFrame#row[]= method. For example, using the previous dataframe df:
df.row[:a] = [23,35,2]
df
#=>
#<Daru::DataFrame:73956870 #name = c8a65ffe-217d-43bb-b6f8-50d2530ec053 #size = 4>
# a b r
# 0 1 5 11
# 1 2 6 22
# 2 3 7 33
# a 23 35 2
Assigning a Daru::Vector will align according to the names of the vectors of the Daru::DataFrame.
You can see further details in these notebooks.
Hope this answers your question.

Bitmasking in Ruby: Get numbers which generated the bitmask

Currently I am storing a combination of a group of items as a single integer (bitmasked value) as in the example below:
Example:
1 - Orange
2 - Banana
4 - Cherry
8 - Apple
And then if the user selects Orange (1) and Apple (8) then the sum of those is 9.
And it is always and only when those two items are combined this value is 9.
And you are able to recover the original two numbers which were used to generate this number.
Here is an example website which does the trick:
http://www.tfxsoft.com/playground/calc.php
What I need:
I need an algoritm (preferrably in Ruby) which would take the sum (9) of those two bitmask values and return the values which it "contains" ( 1 and 4).
I think this might be what you're looking for:
FRUIT = { 1 => 'Orange', 2 => 'Banana', 4 => 'Cherry', 8 => 'Apple' }
def mask_fruit(a, b) a | b end
def unmask_fruit(masked)
FRUIT.select { |k, _| (masked | k) == masked }
end
mask = mask_fruit 1, 8 # => 9
unmask_fruit mask # => {1=>"Orange", 8=>"Apple"}
As I understand you want to find position of bits. Here is simple but not optimal solution:
2.1.5 :033 > 9.to_s(2).reverse.chars.map.with_index { |b, i| b == "1" ? i + 1 : nil }.compact
=> [1, 4]

Print numbers in a range

I am trying to print all numbers between 1 and 50, using the following code:
[1..50].each{|n| puts n}
but the console print
[1..50]
I want to print something like this
1
2
3
4
...
50
Try the following code:
(1..50).each { |n| puts n }
The problem is that you're using [] delimiter instead of () one.
You can use [1..10] with a minor tweak:
[*1..10].each{ |i| p i }
outputs:
1
2
3
4
5
6
7
8
9
10
The * (AKA "splat") "explodes" the range into its components, which are then used to populate the array. It's similar to writing (1..10).to_a.
You can also do:
puts [*1..10]
to print the same thing.
So, try:
[*1..10].join(' ') # => "1 2 3 4 5 6 7 8 9 10"
or:
[*1..10] * ' ' # => "1 2 3 4 5 6 7 8 9 10"
To get the output you want.
The error here is that you are creating an Array object with a range as its only element.
> [1..10].size
=> 1
If you want to call methods like each on a range, you have to wrap the range in parentheses to avoid the method being called on the range's last element rather than on the range itself.
=> (1..10).each { |i| print i }
12345678910
Other ways to achieve the same:
(1..50).each { |n| print n }
1.up_to(50) { |n| print n }
50.times { |n| print n }
You can cast your range (in parentheses) to an array ([1 2 3 4 5 6... 48 49 50]) and join each item (e.g. with ' ' if you want all items in one line).
puts (1..50).to_a.join(' ')
# => 1 2 3 4 5 6 7 ... 48 49 50

Resources