<jupyter_start><jupyter_text>---     Department of Data ScienceCourse: Tools and Techniques for Data Science---Instructor: <NAME>, Ph.D.     Lecture 3.7 (NumPy-07)   Learning agenda of this notebook  1. Concatenating of NumPy Arrays    2. Stacking of NumPy Arrays     3. Splitting NumPy Arrays<jupyter_code># To install this library in Jupyter notebook
#import sys
#!{sys.executable} -m pip install numpy
import numpy as np
np.__version__ , np.__path__<jupyter_output><empty_output><jupyter_text>1. Concatenating NumPy Arrays The `np.concatenate()` method is used to join arrays with respect to given axis.```np.concatenate(tup, axis=0)```- Where `tup` is comma separated ndarrays- If axis is 0, it will join the arrays by row-wise (vertically). For 2-D arrays, the number of columns must match.- If axis is 1, it will join the arrays by column-wise (horizontally). For 2-D arrays, the number of rows must match.- For 1-D arrays, the arrays can be of any size/length.- The original arrays remains as such, as it does not occur in-place. **Example:** Concatenate two 1-D Arrays along axis = 0 (row wise). The 1-D arrays can be of any size/length.<jupyter_code>import numpy as np
arr1 = np.random.randint(low = 1, high = 100, size = 5)
arr2 = np.random.randint(low = 1, high = 100, size = 3)
print("arr1 = ", arr1)
print("arr2 = ", arr2)

arr3 = np.concatenate((arr1, arr2))
arr3 = np.concatenate((arr1, arr2), axis=0)
print("\nnp.concatenate((arr1,arr2)) = ", arr3)<jupyter_output>arr1 =  [27 68 57  7 45]
arr2 =  [82 79 12]

np.concatenate((arr1,arr2)) =  [27 68 57  7 45 82 79 12]<jupyter_text>You cannot concatenate 1-D arrays on `axis=1`, as it do not exist :) **Example:** Concatenate two 2-D Arrays along `axis=0` (vertically/row-wise). The number of columns of two arrays must match.<jupyter_code>arr1 = np.random.randint(low = 1, high = 10, size = (2,3))
arr2 = np.random.randint(low = 1, high = 10, size = (3,3))
print("arr1 = \n", arr1)
print("arr2 = \n", arr2)

arr3 = np.concatenate((arr1, arr2), axis=0)
print("\nnp.concatenate((arr1,arr2)) = \n", arr3)<jupyter_output>arr1 = 
 [[8 3 4]
 [9 7 3]]
arr2 = 
 [[5 2 7]
 [1 9 4]
 [4 7 3]]

np.concatenate((arr1,arr2)) = 
 [[8 3 4]
 [9 7 3]
 [5 2 7]
 [1 9 4]
 [4 7 3]]<jupyter_text>**Example:** Concatenate two 2-D Arrays along `axis=1` (horizontally/column-wise). The number of rows of two arrays must match.<jupyter_code>arr1 = np.random.randint(low = 1, high = 10, size = (2,2))
arr2 = np.random.randint(low = 1, high = 10, size = (2,3))
print("arr1 = \n", arr1)
print("arr2 = \n", arr2)

arr3 = np.concatenate((arr1, arr2), axis=1)
print("\nnp.concatenate((arr1,arr2)) = \n", arr3)<jupyter_output>arr1 = 
 [[5 8]
 [3 8]]
arr2 = 
 [[4 2 7]
 [7 5 6]]

np.concatenate((arr1,arr2)) = 
 [[5 8 4 2 7]
 [3 8 7 5 6]]<jupyter_text>2. Stacking NumPy Arrays- Concatenating joins a sequence of arrays along an existing axis, and stacking joins a sequence of arrays along existing as well as along a new axis.- We can perform stacking along three dimensions:    - `np.vstack()` : it performs vertical stacking along the rows.    - `np.hstack()` : it performs horizontal stacking along with the columns.    - `np.dstack()` : it performs in-depth stacking along a new third axis (depth).**Note:** - `numpy.stack()` is the most general of the three methods, offering an axis parameter for specifying which way to put the arrays together.- `np.column_stack()` is used to stack 1-D arrays as columns into 2-D array.- `np.row_stack()` is used to stack 1-D arrays as rows into 2-D array.   a. Use `np.vstack()` for Row-Wise ConcatenationThe `np.vstack()` method is used to stack arrays vertically or row-wise.```np.vstack(tup)```- Where `tup` is comma separated ndarrays- 1-D arrays must have the same size/length, while for 2-D arrays, the number of columns must match.- It returns an ndarray formed by stacking the given arrays, will be at least 2-D.- The original arrays remains as such, as it does not occur in-place. **Example:** Perform vertical stacking of two 1-D Arrays, which must have the same size/length.<jupyter_code>import numpy as np
arr1 = np.random.randint(low = 1, high = 10, size = 4)
arr2 = np.random.randint(low = 1, high = 10, size = 4)

print("arr1 = ", arr1)
print("arr2 = ", arr2)
  
arr3 = np.vstack((arr1, arr2))

print ("\nnp.vstack((arr1, arr2)):\n ", arr3)<jupyter_output>arr1 =  [8 7 7 7]
arr2 =  [6 6 8 2]

np.vstack((arr1, arr2)):
  [[8 7 7 7]
 [6 6 8 2]]<jupyter_text>Note: The output array is a 2-D array **Example:** Perform vertical stacking of two 2-D Arrays. The number of columns of two arrays must match<jupyter_code>arr1 = np.random.randint(low = 1, high = 10, size = (2,3))
arr2 = np.random.randint(low = 1, high = 10, size = (3,3))

print("arr1 = \n", arr1)
print("arr2 = \n", arr2)

arr3 = np.vstack((arr1, arr2))
print ("\n np.vstack((arr1, arr2)):\n ", arr3)<jupyter_output>arr1 = 
 [[1 1 8]
 [1 4 8]]
arr2 = 
 [[3 5 5]
 [4 6 2]
 [2 5 6]]

 np.vstack((arr1, arr2)):
  [[1 1 8]
 [1 4 8]
 [3 5 5]
 [4 6 2]
 [2 5 6]]<jupyter_text>b. Using `np.hstack()` for Column-Wise ConcatenationThe `np.hstack()` method is used to stack arrays horizontally or column-wise.```np.hstack(tup)```- Where `tup` is comma separated ndarrays- 1-D arrays can have any size/length, while for 2-D arrays, the number of rows must match.- It returns an ndarray formed by stacking the given arrays.- The original arrays remains as such, as it does not occur in-place. **Example:** Perform horizontal stacking of two 1-D Arrays, which can be of different  size/length<jupyter_code>arr1 = np.random.randint(low = 1, high = 10, size = 5)
arr2 = np.random.randint(low = 1, high = 10, size = 4)
print("arr1 = ", arr1)
print("arr2 = ", arr2)
  
arr3 = np.hstack((arr1, arr2))
print ("\n np.hstack((arr1, arr2)):\n ", arr3)<jupyter_output>arr1 =  [7 5 4 3 8]
arr2 =  [8 7 9 8]

 np.hstack((arr1, arr2)):
  [7 5 4 3 8 8 7 9 8]<jupyter_text>Note: The output array is a 1-D array **Example:** Perform horizontal stacking of two 2-D Arrays. The number of rows of two arrays must match<jupyter_code>arr1 = np.random.randint(low = 1, high = 10, size = (2,2))
arr2 = np.random.randint(low = 1, high = 10, size = (2,3))
print("arr1 = \n", arr1)
print("arr2 = \n", arr2)

arr3 = np.hstack((arr1, arr2))
print ("\n np.hstack((arr1, arr2)):\n ", arr3)<jupyter_output>arr1 = 
 [[7 6]
 [4 3]]
arr2 = 
 [[8 5 6]
 [1 9 5]]

 np.hstack((arr1, arr2)):
  [[7 6 8 5 6]
 [4 3 1 9 5]]<jupyter_text>e. Using `np.stack()`- The `np.stack()` method is used to join a sequence of same dimension arrays along a new axis.- The axis parameter specifies the index of the new axis in the dimensions of the result. - For example, if axis=0 it will be the first dimension and if axis=-1 it will be the last dimension.```np.stack(a1, a2, a3, ..., axis=0)```- Where `tup` is comma separated ndarrays- 1-D or 2-D arrays must have the same shape, while n-D arrays must have the same shape along all but the third axis.- It returns the array formed by stacking the given arrays, which has one more dimension than the input arrays.- This function makes most sense for arrays with up to 3 dimensions. For instance, for pixel-data with a height (first axis), width (second axis), and r/g/b channels (third axis).**Note:** Concatenating joins a sequence of tensors along an existing axis, and stacking joins a sequence of tensors along a new axis **Example:** Perform stacking of two 1-D Arrays, which must have the same size/shape.<jupyter_code>import numpy as np
arr1 = np.random.randint(low = 1, high = 10, size = 4)
arr2 = np.random.randint(low = 1, high = 10, size = 4)
print("arr1 = ", arr1)
print("arr2 = ", arr2)
  
# Stacking the two arrays along axis 0
arr3 = np.stack((arr1, arr2), axis = 0)
print ("\n np.stack(arr1, arr2, axis=0):\n ", arr3)
  
# Stacking the two arrays along axis 1
arr4 = np.stack((arr1, arr2), axis = 1)
print ("\n np.stack((arr1, arr2), axis=1):\n ", arr4)<jupyter_output>arr1 =  [6 3 6 9]
arr2 =  [2 3 7 3]

 np.stack(arr1, arr2, axis=0):
  [[6 3 6 9]
 [2 3 7 3]]

 np.stack((arr1, arr2), axis=1):
  [[6 2]
 [3 3]
 [6 7]
 [9 3]]<jupyter_text>**Example:** Perform stacking of two 2-D Arrays, which must have the same size/shape.<jupyter_code>import numpy as np
arr1 = np.random.randint(low = 1, high = 10, size = (2,3))
arr2 = np.random.randint(low = 1, high = 10, size = (2,3))
print("arr1 = \n", arr1)
print("arr2 = \n", arr2)

# Stacking the two arrays along axis 0
arr3 = np.stack((arr1, arr2), axis = 0)
print ("\n np.stack((arr1, arr2), axis=0): \n", arr3)
  
# Stacking the two arrays along axis 1
arr4 = np.stack((arr1, arr2), axis = 1)
print ("\n np.stack((arr1, arr2), axis=1):\n ", arr4)

# Stacking the two arrays along last axis
arr5 = np.stack((arr1, arr2), axis = -1)
print ("\n np.stack((arr1, arr2), axis=-1):\n ", arr5)<jupyter_output>arr1 = 
 [[7 9 1]
 [5 3 8]]
arr2 = 
 [[4 5 1]
 [9 4 5]]

 np.stack((arr1, arr2), axis=0): 
 [[[7 9 1]
  [5 3 8]]

 [[4 5 1]
  [9 4 5]]]

 np.stack((arr1, arr2), axis=1):
  [[[7 9 1]
  [4 5 1]]

 [[5 3 8]
  [9 4 5]]]

 np.stack((arr1, arr2), axis=-1):
  [[[7 4]
  [9 5]
  [1 1]]

 [[5 9]
  [3 4]
  [8 5]]]<jupyter_text>3. Splitting NumPy Arrays- Splitting is reverse operation of Joining, and is used to split one array into multiple arrays....- We can perform splitting along three dimensions:    - `np.split()` : Split array into a list of multiple sub-arrays of equal size.    - `np.hsplit()` : Split array into multiple sub-arrays horizontally (column wise).    - `np.vsplit()` : Split array into multiple sub-arrays vertically (row wise).  a. The `np.split()` and `np.array_split()` Methods  - The `np.split()` method splits an array into multiple sub-arrays of equal sizes.```np.split(arr, size, axis=0)```- Where,    - `arr` is the array to be divided into sub-arrays.    - `size` is an size of the sub-arrays, into which `arr` will be divided along the axis.     - `axis` is the axis along which to split, default is 0.- If such split is not possible, an error is raised. To avoid error you can use `np.array_split()`- It returns a list of sub-arrays as views into `arr` **Example:** Use of `split()`<jupyter_code>arr1 = np.random.randint(low = 1, high = 10, size = 20)
print("arr1:\n",arr1)

# The split size must be a factor of array size (can be 1, 2, 4, 5, 10) 
print("\nSub-arrays: \n", np.split(arr1, 2))<jupyter_output>arr1:
 [4 3 4 4 9 5 3 2 8 1 9 6 1 1 4 8 4 9 6 3]

Sub-arrays: 
 [array([4, 3, 4, 4, 9, 5, 3, 2, 8, 1]), array([9, 6, 1, 1, 4, 8, 4, 9, 6, 3])]<jupyter_text>**Example:** Use of `array_split()`<jupyter_code># create an array of float type
arr1 = np.random.randint(low = 1, high = 10, size = 20)
print("arr1:\n",arr1)

# The array_split() will not flag an error if size is not a factor of array size (will manage)
print("\nSub-arrays: \n", np.array_split(arr1, 3))<jupyter_output>arr1:
 [6 1 2 6 2 1 7 8 5 1 7 5 2 7 9 1 1 7 3 6]

Sub-arrays: 
 [array([6, 1, 2, 6, 2, 1, 7]), array([8, 5, 1, 7, 5, 2, 7]), array([9, 1, 1, 7, 3, 6])]<jupyter_text>b. The `np.hsplit()` Method- The `np.hsplit()` method is used to split an array into multiple sub-arrays horizontally (column-wise). - The `np.hsplit()` is equivalent to split with axis=1, the array is always split along the second axis regardless of the array dimension.```np.hsplit(arr, size)```- Where,    - `arr` is the array to be divided into sub-arrays.    - `size` is the size of the sub-arrays, into which `arr` will be divided along the axis. For `hsplit()`, size argument should be a factor of number of columns, else it flags an error- It returns a list of sub-arrays as views into `arr` **Example:**<jupyter_code># create an array of float type with 4 rows and 5 columns with sequential values from 0 to 15
arr1 = np.arange(16.0).reshape(4,4)
# print array
print("arr1:\n",arr1)
print("shape: ", arr1.shape)
# horizontally split array into 2 subarrays
print("\nSub-arrays: \n", np.hsplit(arr1, 2))<jupyter_output>Sub-arrays: 
 [array([[ 0.,  1.],
       [ 4.,  5.],
       [ 8.,  9.],
       [12., 13.]]), array([[ 2.,  3.],
       [ 6.,  7.],
       [10., 11.],
       [14., 15.]])]<jupyter_text>c. The `np.vsplit()` Method- The `np.vsplit()` method is used to split an array into multiple sub-arrays vertically (row-wise). Not applicable for 1-D array.- The `np.vsplit()` is equivalent to split with axis=0, the array is always split along the first axis regardless of the array dimension.```np.vsplit(arr, size)```-Where,   - `arr` is the array to be divided into sub-arrays.   - `size` is the size of the sub-arrays, into which `arr` will be divided along the axis. For `vsplit()`, size argument should be a factor of number of rows, else it flags an error- It returns a list of sub-arrays as views into `arr` **Example:**<jupyter_code># create an array of float type with 4 rows and 5 columns with sequential values from 0 to 19
arr1 = np.arange(20.0).reshape(4,5)
print("arr1:\n",arr1)
print("shape: ", arr1.shape)
# vertically split array into 2 subarrays (remember size argument must be a factor of number of rows )
print("\nSub-arrays: \n", np.vsplit(arr1, 2))<jupyter_output>Sub-arrays: 
 [array([[0., 1., 2., 3., 4.],
       [5., 6., 7., 8., 9.]]), array([[10., 11., 12., 13., 14.],
       [15., 16., 17., 18., 19.]])]
{'fraction_non_alphanumeric': 0.15121471278286536, 'fraction_numerical': 0.057746159085748885, 'mean_word_length': 3.7294201861130993, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '14', 'dir': 'jupyter-structured-clean-dedup', 'id': '220803', 'license': 'BSL-1.0', 'n_tokens_mistral': 5315, 'n_tokens_neox': 4731, 'n_words': 1881, 'path': 'data-science-master/Section-3-Python-for-Data-Scientists/Lec-3.07(NumPy-07-StackingandSplitting).ipynb', 'repo_name': 'Hamid-Ali-99/Python_Just_Python', 'size': '13225'}