download (2)

Download as pdf or txt
Download as pdf or txt
You are on page 1of 10

keyboard_arrow_down Numpy 4

keyboard_arrow_down Content
Shallow vs Deep Copy

view()
copy()

Array Splitting

split()
hsplit()
vsplit()

Array Stacking

hstack()
vstack()
concatenate()

Post Read - Image Manipulation

keyboard_arrow_down Views vs Copies (Shallow vs Deep Copy)


Numpy manages memory very efficiently,
which makes it really useful while dealing with large datasets.

But how does it manage memory so efficiently?

Let's create some arrays to understand what's happens while using numpy.

import numpy as np

# We'll create a np array

a = np.arange(4)
a

array([0, 1, 2, 3])

# Reshape array `a` and store in `b`

b = a.reshape(2, 2)
b

array([[0, 1],
[2, 3]])

Now we will make some changes to our original array a .

a[0] = 100
a

array([100, 1, 2, 3])

What will be values if we print array b ?

array([[100, 1],
[ 2, 3]])

Array b got automatically updated


Array b got automatically updated
This is an example of numpy using Shallow Copy of data.

What happens here?

Numpy re-uses data as much as possible instead of duplicating it.


This helps numpy to be efficient.

When we created b=a.reshape(2,2)

Numpy did NOT make a copy of a to store in b , as we can clearly see.


It is using the same data as in a .
It just looks different (reshaped) in b .
That is why, any changes in a automatically gets reflected in b .

Now, let's see an example where Numpy will create a Deep Copy of data.

a = np.arange(4)
a

array([0, 1, 2, 3])

# Create `c`

c = a + 2
c

array([2, 3, 4, 5])

# We make changes in `a`

a[0] = 100
a

array([100, 1, 2, 3])

array([2, 3, 4, 5])

np.shares_memory(a, c) # Deep Copy

False

As we can see, c did not get affected on changing a .

Because it is an operation.
A more permanent change in data.
So, Numpy had to create a separate copy for c - i.e., deep copy of array a for array c .

keyboard_arrow_down Conclusion:

Numpy is able to use same data for simpler operations like reshape → Shallow Copy.
It creates a copy of data where operations make more permanent changes to data → Deep Copy.

Is there a way to check whether two arrays are sharing memory or not?

Yes, np.shares_memory() function

a= np.arange(10)
a

array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

b = a[::2]
b
array([0, 2, 4, 6, 8])

np.shares_memory(a,b)

True

Notice that Slicing creates shallow copies.

a[0] = 1000

array([1000, 2, 4, 6, 8])

a = np.arange(6)
a

array([0, 1, 2, 3, 4, 5])

b = a[a % 1 == 0]
b

array([0, 1, 2, 3, 4, 5])

b[0] = 10

a[0]

np.shares_memory(a,b)

False

Note:

Shallow Copy - Reshaping, Slicing...


Deep Copy - Arithmetic Operations, Masking...

a = np.arange(10)

a_shallow_copy = a.view()
# Creates a shallow copy of a

np.shares_memory(a_shallow_copy, a)

True

a_deep_copy = a.copy()
# Creates a deep copy of a

np.shares_memory(a_deep_copy, a)

False

keyboard_arrow_down .view()

Returns view of the original array.


Any changes made in new array will be reflected in original array.

Documentation: https://numpy.org/doc/stable/reference/generated/numpy.ndarray.view.html
arr = np.arange(10)
arr

array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

view_arr = arr.view()
view_arr

array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

Let's modify the content of view_arr and check whether it modified the original array as well.

view_arr[4] = 420
view_arr

array([ 0, 1, 2, 3, 420, 5, 6, 7, 8, 9])

arr

array([ 0, 1, 2, 3, 420, 5, 6, 7, 8, 9])

np.shares_memory(arr, view_arr)

True

Notice that changes in view array are reflected in original array.

keyboard_arrow_down .copy()

Returns a copy of the array.


Changes made in new array are not reflected in the original array.

Documentation ( .copy() ): https://numpy.org/doc/stable/reference/generated/numpy.ndarray.copy.html#numpy.ndarray.copy

Documentation: ( np.copy() ): https://numpy.org/doc/stable/reference/generated/numpy.copy.html

arr = np.arange(10)
arr

array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

copy_arr = arr.copy()
copy_arr

array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

Let's modify the content of copy_arr and check whether it modified the original array as well.

copy_arr[3] = 45
copy_arr

array([ 0, 1, 2, 45, 4, 5, 6, 7, 8, 9])

arr

array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

np.shares_memory(arr, copy)

---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-35-84a6cba2b044> in <cell line: 1>()
----> 1 np.shares_memory(arr, copy)

NameError: name 'copy' is not defined

SEARCH STACK OVERFLOW


Notice that the content of original array were not modified as we changed our copy array.

keyboard_arrow_down Splitting
In addition to reshaping and selecting subarrays, it is often necessary to split arrays into smaller arrays or merge arrays into bigger arrays.

keyboard_arrow_down np.split()

Splits an array into multiple sub-arrays as views.

It takes an argument indices_or_sections .

If indices_or_sections is an integer, n, the array will be divided into n equal arrays along axis.

If such a split is not possible, an error is raised.

If indices_or_sections is a 1-D array of sorted integers, the entries indicate where along axis the array is split.

If an index exceeds the dimension of the array along axis, an empty sub-array is returned correspondingly.

x = np.arange(9)
x

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

np.split(x, 3)

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

IMPORTANT REQUISITE

Number of elements in the array should be divisible by number of sections.

b = np.arange(10)
np.split(b, 3)

---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-38-5033f171e13f> in <cell line: 2>()
1 b = np.arange(10)
----> 2 np.split(b, 3)

1 frames
/usr/local/lib/python3.10/dist-packages/numpy/lib/shape_base.py in split(ary, indices_or_sections, axis)
870 N = ary.shape[axis]
871 if N % sections:
--> 872 raise ValueError(
873 'array split does not result in an equal division') from None
874 return array_split(ary, indices_or_sections, axis)

ValueError: array split does not result in an equal division

SEARCH STACK OVERFLOW

b[0:-1]
np.split(b[0:-1], 3)

# Splitting on the basis of exact indices

c = np.arange(16)
np.split(c, [3, 5, 6])

[array([0, 1, 2]),
array([3, 4]),
array([5]),
array([ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])]

keyboard_arrow_down np.hsplit()
Splits an array into multiple sub-arrays horizontally (column-wise).

x = np.arange(16.0).reshape(4, 4)
x

array([[ 0., 1., 2., 3.],


[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[12., 13., 14., 15.]])

Think of it this way:

There are 2 axis to a 2D array

1. 1st axis - Vertical axis


2. 2nd axis - Horizontal axis

Along which axis are we splitting the array?

The split we want happens across the 2nd axis (Horizontal axis)
That is why we use hsplit()

So, try to think in terms of "whether the operation is happening along vertical axis or horizontal axis".

We are splitting the horizontal axis in this case.

np.hsplit(x, 2)

[array([[ 0., 1.],


[ 4., 5.],
[ 8., 9.],
[12., 13.]]),
array([[ 2., 3.],
[ 6., 7.],
[10., 11.],
[14., 15.]])]

np.hsplit(x, np.array([3, 6]))

[array([[ 0., 1., 2.],


[ 4., 5., 6.],
[ 8., 9., 10.],
[12., 13., 14.]]),
array([[ 3.],
[ 7.],
[11.],
[15.]]),
array([], shape=(4, 0), dtype=float64)]

keyboard_arrow_down np.vsplit()

Splits an array into multiple sub-arrays vertically (row-wise).

x = np.arange(16.0).reshape(4, 4)
x

array([[ 0., 1., 2., 3.],


[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[12., 13., 14., 15.]])

Now, along which axis are we splitting the array?

The split we want happens across the 1st axis (Vertical axis)
That is why we use vsplit()

Again, always try to think in terms of "whether the operation is happening along vertical axis or horizontal axis".

We are splitting the vertical axis in this case.

np.vsplit(x, 2)

[array([[0., 1., 2., 3.],


[4., 5., 6., 7.]]),
array([[ 8., 9., 10., 11.],
[12., 13., 14., 15.]])]

np.vsplit(x, np.array([3]))

[array([[ 0., 1., 2., 3.],


[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]]),
array([[12., 13., 14., 15.]])]

keyboard_arrow_down Stacking
a = np.arange(1, 5)
b = np.arange(2, 6)
c = np.arange(3, 7)

keyboard_arrow_down np.vstack()

Stacks a list of arrays vertically (along axis 0 or 1st axis).


For example, given a list of row vectors, appends the rows to form a matrix.

np.vstack([b, c, a])

array([[2, 3, 4, 5],
[3, 4, 5, 6],
[1, 2, 3, 4]])

a = np.arange(1, 5)
b = np.arange(2, 4)
c = np.arange(3, 10)

np.vstack([b, c, a])

---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-49-5148cb6ebc5f> in <cell line: 1>()
----> 1 np.vstack([b, c, a])

2 frames
/usr/local/lib/python3.10/dist-packages/numpy/core/overrides.py in concatenate(*args, **kwargs)

ValueError: all the input array dimensions for the concatenation axis must match exactly, but along dimension 1, the arra

SEARCH STACK OVERFLOW


keyboard_arrow_down np.hstack

Stacks a list of arrays horizontally (along axis 1 or 2nd axis).

a = np.arange(5).reshape(5, 1)
a

array([[0],
[1],
[2],
[3],
[4]])

b = np.arange(15).reshape(5, 3)
b

array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11],
[12, 13, 14]])

np.hstack([a, b])

array([[ 0, 0, 1, 2],
[ 1, 3, 4, 5],
[ 2, 6, 7, 8],
[ 3, 9, 10, 11],
[ 4, 12, 13, 14]])

keyboard_arrow_down np.concatenate()

Can perform both vstack and hstack


Creates a new array by appending arrays after each other, along a given axis.

Provides similar functionality, but it takes a keyword argument axis that specifies the axis along which the arrays are to be concatenated.

The input array to concatenate() needs to be of dimensions atleast equal to the dimensions of output array.

a = np.array([1,2,3])
a

array([1, 2, 3])

b = np.array([[1,2,3], [4,5,6]])
b

array([[1, 2, 3],
[4, 5, 6]])

np.concatenate([a, b], axis = 0)

---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-55-1a93c4fe21df> in <cell line: 1>()
----> 1 np.concatenate([a, b], axis = 0)

/usr/local/lib/python3.10/dist-packages/numpy/core/overrides.py in concatenate(*args, **kwargs)

ValueError: all the input arrays must have same number of dimensions, but the array at index 0 has 1 dimension(s) and the

SEARCH STACK OVERFLOW

concatenate() can only work if both a and b have the same number of dimensions.

a = np.array([[1,2,3]])
b = np.array([[1,2,3], [4,5,6]])

np.concatenate([a, b], axis = 0) # axis = 0 -> vstack


array([[1, 2, 3],
[1, 2, 3],
[4, 5, 6]])

a = np.arange(6).reshape(3, 2)
b = np.arange(9).reshape(3, 3)

np.concatenate([a, b], axis = 1) # axis = 1 -> hstack

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

a = np.array([[1,2], [3,4]])
b = np.array([[5,6,7,8]])

np.concatenate([a, b], axis = None)

# axis = None joins and converts to 1D

array([1, 2, 3, 4, 5, 6, 7, 8])

Question: What will be the output of this?

a = np.array([[1, 2], [3, 4]])


b = np.array([[5, 6]])
np.concatenate((a, b), axis=0)

a = np.array([[1, 2], [3, 4]])


a

array([[1, 2],
[3, 4]])

b = np.array([[5, 6]])
b

array([[5, 6]])

np.concatenate((a, b), axis=0)

array([[1, 2],
[3, 4],
[5, 6]])

How did it work?

Dimensions of a is 2 ×2
What is the dimensions of b ?

1-D array ?? - NO
Look carefully!!
b is a 2-D array of dimensions 1 ×2
axis = 0 ---> It's a vertical axis

So, changes will happen along vertical axis


So, b gets concatenated below a

Question: What will be the result of this concatenation operation?

a = np.array([[1, 2], [3, 4]])


b = np.array([[5, 6]])
np.concatenate((a, b.T), axis=1)

a = np.array([[1, 2], [3, 4]])


a
array([[1, 2],
[3, 4]])

b = np.array([[5, 6]])
b

array([[5, 6]])

np.concatenate((a, b.T), axis=1)

array([[1, 2, 5],
[3, 4, 6]])

What happened here?

Dimensions of a is again 2 ×2
Dimensions of b is again 1 ×2
So, Dimensions of b.T will be 2 × 1

axis = 1 ---> It's a horizontal axis

So, changes will happen along horizontal axis


So, b.T gets concatenated horizontally to a

keyboard_arrow_down Extra-reading material


Object arrays
Image Manipulation

Code Text

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy