The array is a data structure for most programming languages. It is to represent orderly datasets. Having said that, I suppose it might also occur to you that, lists seem to be such a structure too. Yes, indeed. A list may be used as an array in Python. Besides, there is also a special array type in Python. Then, why does NumPy still need such a data structure like ndarray? Coming soon. Lists and tuples can be used as arrays, but they still differ slightly from arrays. In a list, for example, its elements may be of any type. So, what are saved in the list are the pointers of objects. For example, to save a simple list, say, containing 4 elements like "1, 2, 3, 4", it needs 4 pointers and 4 integer objects. That would waste memory and computing time. By contrast, the "array" module is not a built-in module of Python. It requires additional installation. Then, create arrays through the "array" function. It also provides insert(), append() and similar functions. But it does not support N-dimensional array and the functions do not have rich uses, thus not frequently used. By contrast, "ndarray" is a basic data structure in NumPy, also known as "array". As its name suggests, it is an array. All elements in the array are of the same type. Since "array" has abundant functions, most of their performances are very powerful. Well, let's learn about "ndarray" first. There's an array, 5*5, Let's analyze this array. We may actually regard this 5*5 array as one composed of five one-dimensional arrays. And, each one-dimensional array consists of 5 elements. Here, this is the first dimension, known as Axis 0. This is the second dimension, known as Axis 1. The quantity of axis/axes is "rank". There are 2 axes in this array, so the value of rank here is 2. Then, let's see "axis". Many functions, when used, can be followed by such an argument "axis" like axis = 0. What does it mean? It means operating along Axis 0. Actually it means to operate each column. How about axis = 1? It obviously means to operate each row. "ndarray" has some basic attributes. For example, "ndim" can be used for calculating its rank. "shape" can be used for calculating its dimensions. "size" can be used for calculating the total quantity of elements. For example, look at this array here. Its rank is 2. Its dimension is (5,5). The total quantity of elements is 25. Well, next, let's look at the method of creating "array". NumPy provides many functions for creating ndarray. The most basic one is the function "array()". We can create a one-dimensional array or create a two-dimensional array. In addition, functions such as "arange()", "random()", "linspace()" are often used to create arrays. "arange", this one should be familiar to you. It's similar to our "range", but it can handle floating-point numbers. And, "random()" is to get a random number. The linspace() function is also very common. It creates a linearly spaced array between the starting, the ending point and with a specified quantity of numbers. Sure, the ending point may be not included. Set it as "False". It is "True" by default. Besides, we also often use "ones()", "zeros()" and similar functions to create such basic arrays. Moreover, there's a very special function "fromfunction()". It creates an array of a certain dimension from a function. The function here is like this. In fact, we may write this function like this: return (i+1)*(j+1). Have a look. Does it actually generate a 9*9 multiplication table? Its effect is like this: from "one times one equals one" to "nine times nine equals eighty-one". Funny, right? Let's briefly demonstrate them. Create an array with the "array()" function. Suppose we're creating such an array "2*3". Let's look at the attributes of this array. This is its rank, dimension, quantity of its elements. Let's create another element array. For example, we use the "arange()" function. "y" is created successfully. ndarray provides many methods of operation and calculation to enable use to get our desired result. For example, let's have a look. This symbol must be quite familiar, "slicing". Then, what does it mean if we choose 0 to 2? It means we choose Row 0 and Row 1. If we write nothing for the first dimension, it would mean we want all rows. Then, let's look at the 0 and 1 at the back. This is the column, meaning choosing Column 0 and Column 1. So, the result is "1 2 4 5", and we may add both dimensions in the argument. We choose the first row then, so, as we see, the results of Column 0 and Column 1 of Row 1 are 4 and 5. We may also traverse an array with such a method. We may also operate ndarray with some functions. For example, as we see, the dimension of this array is 2 * 3. When we're printing, we may change its dimension with the "reshape()" function. We may change it into a 3 * 2 array. Look at the result. Has it changed? Is that interesting? With this method, however, as we see, the original form of aArray remains the same. If we really want to change it shape, we may use the "resize()" function. As we see, the result has changed. There's another pair of frequently used functions "vstack()" and "hstack()", one is to stack vertically, and the other is stack horizontally. For ndarray, there are also some basic operators for operation, like multiplication and addition. Besides, here we see two very special arrays. They can even be added. This is special in NumPy, i.e. some arrays with dissimilar shapes can be operated sometimes. This is a broadcasting concept. If interested, you can learn more about it. Besides, we may use some methods to conduct various operations to arrays, like "sum()" to get the sum. As we mentioned before, we may apply such arguments to add numbers in column or in rows. This is to return the minimum value. This is to return the index of the maximum value. In this instance here, the value and the index happen to be the same. And, you must know this one, acquiring the average value, var and std mean variance and standard variance, respectively. There are also some dedicated applications for ndarray, like very common applications in linear algebra. We may resort to some functions in NumPy for various calculations. For example, here, we may use the "dot()" function to calculate the inner product of matrix. In addition, in NumPy, there's a "linalg" module, sharing the same name as in SciPy library. It can be roughly regarded as a subset of the corresponding module in SciPy library. It's also possible for us to apply many of its functions for various operation. The "det()" function, for example, can be used to calculate the determinant of matrix. "inv()", to calculate inverse matrixes. At the end of ndarray, let's talk about the "ufunc" function, i.e., the universal function. The universal function in NumPy is a kind of function that can operate each element in an array like these. They are not all of them. We can view all function names at the official website. The universal function has some own methods. like "reduce()", "accumulate()" These functions are realized at the C language level, so the calculating speed is very high. In case of big data quantities, in particular, it is faster than the corresponding function in "math". Let's look at an example like this: It is to calculate the quadratic result of "sin(t)" of a group of numbers. We use the "clock()" function in "time" to calculate the operating time. Compare the two. Let's try this program. Well, Let's execute this program. As we see, the execution result is like this: Use the "pow()" and "sin()" functions in the "math" library. Its operating time is like this: while the operating time with the universal function is like this: As we see, the difference is still big. For this reason, when dealing with big data quantities, we should prefer the universal function in NumPy to perform the task.