DEV Community

kojix2
kojix2

Posted on

9

NArray - Ruby equivalent of NumPy

ruby narray

Want to do fast calculations in Ruby? NArray is your friend!

NArray οΌ† Cumo

Numo::NArray

GitHub

NArray is a powerful N-dimensional array library for science computing in Ruby. Machine learning libraries such as Rumale and Red Chainer use NArray.

Cumo

GitHub

Cumo (pronounced "koomo") is a CUDA-aware, GPU-optimized numerical library that offers a significant performance boost over Ruby Numo, while (mostly) maintaining drop-in compatibility.

NArray Data types

Integer Unsigned Integer Float Complex number
Numo::Int8 Numo::UInt8 Numo::SFloat Numo::SComplex
Numo::Int16 Numo::UInt16 Numo::DFloat Numo::DComplex
Numo::Int32 Numo::UInt32
Numo::Int64 Numo::UInt64

Import the Library

gem install numo-narray
Enter fullscreen mode Exit fullscreen mode
require 'numo/narray'
include Numo
Enter fullscreen mode Exit fullscreen mode

Creating Arrays

Int32[1,2,3]
Enter fullscreen mode Exit fullscreen mode

[1, 2, 3]

Int32.new(3,3).seq
Enter fullscreen mode Exit fullscreen mode

[[0, 1, 2],
[3, 4, 5],
[6, 7, 8]]

a = [[0, 1], [2, 3]]
Int32[*a]
Enter fullscreen mode Exit fullscreen mode

[[0, 1],
[2, 3]]

Int32[1..5]
Enter fullscreen mode Exit fullscreen mode

[1, 2, 3, 4, 5]

Int32[1...5]
Enter fullscreen mode Exit fullscreen mode

[1, 2, 3, 4]

Initial Placeholders

Create an array of zeros

x = Int32.zeros(3,3)
Enter fullscreen mode Exit fullscreen mode

[[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]

Create an array of ones

x = Int32.ones(3,3)
Enter fullscreen mode Exit fullscreen mode

[[1, 1, 1],
[1, 1, 1],
[1, 1, 1]]

Create an array of twos

z = y.fill 2
Enter fullscreen mode Exit fullscreen mode

[[2, 2, 2],
[2, 2, 2],
[2, 2, 2]]

Create a 3x3 identity matrix

y = Int32.eye(3,3)
Enter fullscreen mode Exit fullscreen mode

[[1, 0, 0],
[0, 1, 0],
[0, 0, 1]]

Create an array of evenly spaced values

f = DFloat.linspace(-20,20,11)
Enter fullscreen mode Exit fullscreen mode

[-20, -16, -12, -8, -4, 0, 4, 8, 12, 16, 20]

Arithmetic operations

require 'numo/narray'
include Numo
Enter fullscreen mode Exit fullscreen mode
a = Int32.new(3,3).seq
Enter fullscreen mode Exit fullscreen mode

[[0, 1, 2],
[3, 4, 5],
[6, 7, 8]]

b = Int32.new(3,3).seq + 1
Enter fullscreen mode Exit fullscreen mode

[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]

a + b
Enter fullscreen mode Exit fullscreen mode

[[1, 3, 5],
[7, 9, 11],
[13, 15, 17]]

b - a
Enter fullscreen mode Exit fullscreen mode

[[1, 1, 1],
[1, 1, 1],
[1, 1, 1]]

a * b
Enter fullscreen mode Exit fullscreen mode

[[0, 2, 6],
[12, 20, 30],
[42, 56, 72]]

a * 2
Enter fullscreen mode Exit fullscreen mode

[[0, 2, 4],
[6, 8, 10],
[12, 14, 16]]

a * 0.1
Enter fullscreen mode Exit fullscreen mode

[[0, 0.1, 0.2],
[0.3, 0.4, 0.5],
[0.6, 0.7, 0.8]]

Type conversion

a = UInt8[1,2,3]
SFloat.cast(a)
# => Numo::SFloat#shape=[3]
Enter fullscreen mode Exit fullscreen mode

Dot product

c = Int32.new(2,2).seq

# [[0, 1], 
#  [2, 3]]

d = Int32.new(2,1).seq

# [[0], 
#  [1]]

c.dot d

# [[1], 
#  [3]]
Enter fullscreen mode Exit fullscreen mode

install Numo::Linalg

Numo::Linalg.dot(c,d)
Numo::Linalg.matmul(c,d)
# [[1], 
#  [3]]
Enter fullscreen mode Exit fullscreen mode

Inspecting NArray

e = DFloat.new(3,4).seq

# Array dimensions
e.shape              # => [3, 4]

# Length of array
e.size               # => 12

# Number of array dimensions
e.rank               # => 2
e.ndim               # => 2

# Byte size
e.byte_size          # => 96
Enter fullscreen mode Exit fullscreen mode

Convert NArray to string

s = UInt8.ones(2,2).to_string
# => "\x01\x01\x01\x01"
# [[1, 1], 
#  [1, 1]]

UInt8.from_string(d)
# => Numo::UInt8#shape=[4]
# [1, 1, 1, 1]
Enter fullscreen mode Exit fullscreen mode

Convert NArray to Ruby Array

use to_a

a = UInt8[1,2,3]

a.to_a 
Enter fullscreen mode Exit fullscreen mode

NMath

sin cos tan log, etc.

f = DFloat.linspace(-20,20,11)
# [-20, -16, -12, -8, -4, 0, 4, 8, 12, 16, 20]

NMath.sin(f)
# [-0.912945, 0.287903, 0.536573, -0.989358, 0.756802, 0, -0.756802, ...]

NMath.cos(f)
# [-0.912945, 0.287903, 0.536573, -0.989358, 0.756802, 0, -0.756802, ...]

NMath.tanh(f)
# [-1, -1, -1, -1, -0.999329, 0, 0.999329, 1, 1, 1, 1]

NMath.log(f)
# [nan, nan, nan, nan, nan, -inf, 1.38629, 2.07944, 2.48491, 2.77259, ...]

NMath.log10(f)
# [nan, nan, nan, nan, nan, -inf, 0.60206, 0.90309, 1.07918, 1.20412, ...]

NMath.sqrt(f)
# [-nan, -nan, -nan, -nan, -nan, 0, 2, 2.82843, 3.4641, 4, 4.47214]
Enter fullscreen mode Exit fullscreen mode

Subsetting, Slicing, Indexing

a = Int32.new(10,10).seq
# [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 
#  [10, 11, 12, 13, 14, 15, 16, 17, 18, 19], 
#  [20, 21, 22, 23, 24, 25, 26, 27, 28, 29], 
#  [30, 31, 32, 33, 34, 35, 36, 37, 38, 39], 
#  [40, 41, 42, 43, 44, 45, 46, 47, 48, 49], 
#  [50, 51, 52, 53, 54, 55, 56, 57, 58, 59], 
#  [60, 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, 99]]

a[0,true]
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

a[true, 0]
# [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]

a[1..3, 2..4]
# [[12, 13, 14], 
#  [22, 23, 24], 
#  [32, 33, 34]]

a[1]
# 1

a[-1]
# 99

a.diagonal
# [0, 11, 22, 33, 44, 55, 66, 77, 88, 99]

a.transpose
# [[0, 10, 20, 30, 40, 50, 60, 70, 80, 90], 
#  [1, 11, 21, 31, 41, 51, 61, 71, 81, 91], 
#  [2, 12, 22, 32, 42, 52, 62, 72, 82, 92], 
#  [3, 13, 23, 33, 43, 53, 63, 73, 83, 93], 
#  [4, 14, 24, 34, 44, 54, 64, 74, 84, 94], 
#  [5, 15, 25, 35, 45, 55, 65, 75, 85, 95], 
#  [6, 16, 26, 36, 46, 56, 66, 76, 86, 96], 
#  [7, 17, 27, 37, 47, 57, 67, 77, 87, 97], 
#  [8, 18, 28, 38, 48, 58, 68, 78, 88, 98], 
#  [9, 19, 29, 39, 49, 59, 69, 79, 89, 99]]

a.reverse
# [[99, 98, 97, 96, 95, 94, 93, 92, 91, 90], 
#  [89, 88, 87, 86, 85, 84, 83, 82, 81, 80], 
#  [79, 78, 77, 76, 75, 74, 73, 72, 71, 70], 
#  [69, 68, 67, 66, 65, 64, 63, 62, 61, 60], 
#  [59, 58, 57, 56, 55, 54, 53, 52, 51, 50], 
#  [49, 48, 47, 46, 45, 44, 43, 42, 41, 40], 
#  [39, 38, 37, 36, 35, 34, 33, 32, 31, 30], 
#  [29, 28, 27, 26, 25, 24, 23, 22, 21, 20], 
#  [19, 18, 17, 16, 15, 14, 13, 12, 11, 10], 
#  [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]]

a.reshape(4,25)
# [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, ...], 
#  [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, ...], 
#  [50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, ...], 
#  [75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, ...]

a.max
# 99

a.min
# 0

a.minmax
# [0, 99]

a.sum
# 4950

a.sum 0 
# [450, 460, 470, 480, 490, 500, 510, 520, 530, 540]

a > 49
# => Numo::Bit#shape=[10,10]
# [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
#  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
#  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
#  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
#  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
#  [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
#  [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
#  [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
#  [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
#  [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]

bit = (a > 49)
bit.where
# => Numo::Int32#shape=[50]
# [50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, ...]

a.eq 33
# [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
#  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
#  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
#  [0, 0, 0, 1, 0, 0, 0, 0, 0, 0], 
#  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
#  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
#  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
#  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
#  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
#  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

(a.eq 33).where
# => Numo::Int32#shape=[1]
# [33]

a[a > 90]
# [91, 92, 93, 94, 95, 96, 97, 98, 99]
Enter fullscreen mode Exit fullscreen mode
a = Int32.new(10).seq - 5
# [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4]

a.abs
# a = Int32.new(10).seq - 5
# [5, 4, 3, 2, 1, 0, 1, 2, 3, 4]

b = Int32.new(10).seq

b.cumsum
# [0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
Enter fullscreen mode Exit fullscreen mode

Rnadom values

x = DFloat.new(1000).rand
y = DFloat.new(1000).rand
Enter fullscreen mode Exit fullscreen mode

image.png

x = DFloat.new(1000).rand_norm
y = DFloat.new(1000).rand_norm
# rand_norm([mu,[sigma]]) 
Enter fullscreen mode Exit fullscreen mode

image.png

Statistics

a = DFloat.new(100,100).rand_norm(1, 2)
# => Numo::DFloat#shape=[100,100]

a.size
# => 10000

a.mean
# => 0.9941970100670163

a.median
# => Numo::DFloat#shape=[]
# 1.0030267444162986

a.var
# => 3.9539947182922974

a.stddev
# => 1.9884654179271757

a.rms
# => 2.223067028599605
Enter fullscreen mode Exit fullscreen mode

Sorting Arrays

na = Int32[1, 10, 2, 5, 9, 8, 12, 11, 3, 7, 4, 6]

na.sort

#=> Numo::Int32#shape=[12]
#[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

na.max_index
# => 6

na.min_index
# => 0

na.sort_index
=> Numo::Int32#shape=[12]
[0, 2, 8, 10, 3, 11, 9, 5, 4, 1, 7, 6]
Enter fullscreen mode Exit fullscreen mode

View

a = Int8[1,2,3,4,5]
# [1, 2, 3, 4, 5]
b = a.view
# => Numo::Int8(view)#shape=[5]
# [1, 2, 3, 4, 5]

a[0] = 0
b
# => Numo::Int8(view)#shape=[5]
# [0, 2, 3, 4, 5]

b[1] = 0
a
# => Numo::Int8#shape=[5]
# [0, 0, 3, 4, 5]
Enter fullscreen mode Exit fullscreen mode

Saving & Loading

a = Int32.new(2,2).seq

# save
s = Marshal.dump(a)
File.binwrite("data", s)

# load
b = Marshal.load(File.read("data"))
a == b
# true
Enter fullscreen mode Exit fullscreen mode

Combining Arrays

a = Int32[1,2,3]
b = Int32[4,5,6]

a.append b
# [1,2,3,4,5,6]

a.concatenate b
# [1,2,3,4,5,6]

a.hstack b

Int32.hstack [a,b]
# [1,2,3,4,5,6]

Int32.dstack [b,b]
# => Numo::Int32#shape=[2,3,2]
# [[[1, 1], 
#  [2, 2], 
#  [3, 3]], 
# [[4, 4], 
#  [5, 5], 
#  [6, 6]]]
Enter fullscreen mode Exit fullscreen mode

Documents

This is just some of the features of NArray. If you want to know more, please refer to these webpages.

Have a nice day!

Top comments (0)

Image of Docusign

πŸ› οΈ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more