NumPy 源码解析(二十)
.\numpy\numpy\lib\_scimath_impl.pyi
from typing import overload, Any
from numpy import complexfloating
from numpy._typing import (
NDArray,
_ArrayLikeFloat_co,
_ArrayLikeComplex_co,
_ComplexLike_co,
_FloatLike_co,
)
__all__: list[str]
@overload
def sqrt(x: _FloatLike_co) -> Any: ...
@overload
def sqrt(x: _ComplexLike_co) -> complexfloating[Any, Any]: ...
@overload
def sqrt(x: _ArrayLikeFloat_co) -> NDArray[Any]: ...
@overload
def sqrt(x: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...
@overload
def log(x: _FloatLike_co) -> Any: ...
@overload
def log(x: _ComplexLike_co) -> complexfloating[Any, Any]: ...
@overload
def log(x: _ArrayLikeFloat_co) -> NDArray[Any]: ...
@overload
def log(x: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...
@overload
def log10(x: _FloatLike_co) -> Any: ...
@overload
def log10(x: _ComplexLike_co) -> complexfloating[Any, Any]: ...
@overload
def log10(x: _ArrayLikeFloat_co) -> NDArray[Any]: ...
@overload
def log10(x: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...
@overload
def log2(x: _FloatLike_co) -> Any: ...
@overload
def log2(x: _ComplexLike_co) -> complexfloating[Any, Any]: ...
@overload
def log2(x: _ArrayLikeFloat_co) -> NDArray[Any]: ...
@overload
def log2(x: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...
@overload
def logn(n: _FloatLike_co, x: _FloatLike_co) -> Any: ...
@overload
def logn(n: _ComplexLike_co, x: _ComplexLike_co) -> complexfloating[Any, Any]: ...
@overload
def logn(n: _ArrayLikeFloat_co, x: _ArrayLikeFloat_co) -> NDArray[Any]: ...
@overload
def logn(n: _ArrayLikeComplex_co, x: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...
@overload
def power(x: _FloatLike_co, p: _FloatLike_co) -> Any: ...
@overload
def power(x: _ComplexLike_co, p: _ComplexLike_co) -> complexfloating[Any, Any]: ...
@overload
def power(x: _ArrayLikeFloat_co, p: _ArrayLikeFloat_co) -> NDArray[Any]: ...
@overload
def power(x: _ArrayLikeComplex_co, p: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...
@overload
def arccos(x: _FloatLike_co) -> Any: ...
@overload
def arccos(x: _ComplexLike_co) -> complexfloating[Any, Any]: ...
@overload
def arccos(x: _ArrayLikeFloat_co) -> NDArray[Any]: ...
@overload
def arccos(x: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...
@overload
def arcsin(x: _FloatLike_co) -> Any: ...
@overload
def arcsin(x: _ComplexLike_co) -> complexfloating[Any, Any]: ...
@overload
def arcsin(x: _ArrayLikeFloat_co) -> NDArray[Any]: ...
@overload
def arcsin(x: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...
@overload
def arctanh(x: _FloatLike_co) -> Any: ...
@overload
def arctanh(x: _ComplexLike_co) -> complexfloating[Any, Any]: ...
@overload
def arctanh(x: _ArrayLikeFloat_co) -> NDArray[Any]: ...
@overload
def arctanh(x: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...
.\numpy\numpy\lib\_shape_base_impl.py
import functools
import warnings
import numpy._core.numeric as _nx
from numpy._core.numeric import asarray, zeros, zeros_like, array, asanyarray
from numpy._core.fromnumeric import reshape, transpose
from numpy._core.multiarray import normalize_axis_index
from numpy._core._multiarray_umath import _array_converter
from numpy._core import overrides
from numpy._core import vstack, atleast_3d
from numpy._core.numeric import normalize_axis_tuple
from numpy._core.overrides import set_module
from numpy._core.shape_base import _arrays_for_stack_dispatcher
from numpy.lib._index_tricks_impl import ndindex
from numpy.matrixlib.defmatrix import matrix
__all__ = [
'column_stack', 'row_stack', 'dstack', 'array_split', 'split',
'hsplit', 'vsplit', 'dsplit', 'apply_over_axes', 'expand_dims',
'apply_along_axis', 'kron', 'tile', 'take_along_axis',
'put_along_axis'
]
array_function_dispatch = functools.partial(
overrides.array_function_dispatch, module='numpy')
def _make_along_axis_idx(arr_shape, indices, axis):
if not _nx.issubdtype(indices.dtype, _nx.integer):
raise IndexError('`indices` must be an integer array')
if len(arr_shape) != indices.ndim:
raise ValueError(
"`indices` and `arr` must have the same number of dimensions")
shape_ones = (1,) * indices.ndim
dest_dims = list(range(axis)) + [None] + list(range(axis+1, indices.ndim))
fancy_index = []
for dim, n in zip(dest_dims, arr_shape):
if dim is None:
fancy_index.append(indices)
else:
ind_shape = shape_ones[:dim] + (-1,) + shape_ones[dim+1:]
fancy_index.append(_nx.arange(n).reshape(ind_shape))
return tuple(fancy_index)
def _take_along_axis_dispatcher(arr, indices, axis):
return (arr, indices)
@array_function_dispatch(_take_along_axis_dispatcher)
def take_along_axis(arr, indices, axis):
"""
通过匹配 1 维索引和数据切片,从输入数组中取值。
这将沿着指定轴迭代匹配的索引和数据数组中的 1 维切片,并使用前者查找后者中的值。这些切片可以具有不同的长度。
返回一个由匹配的数组组成的新数组。
.. versionadded:: 1.15.0
Parameters
----------
arr : ndarray (Ni..., M, Nk...)
源数组
indices : ndarray (Ni..., J, Nk...)
沿着 `arr` 的每个 1 维切片取出的索引。它必须与 `arr` 的维度匹配,
但 Ni 和 Nj 只需要广播至 `arr`。
"""
if axis is None:
if indices.ndim != 1:
raise ValueError(
'when axis=None, `indices` must have a single dimension.')
arr = arr.flat
arr_shape = (len(arr),)
axis = 0
else:
axis = normalize_axis_index(axis, arr.ndim)
arr_shape = arr.shape
return arr[_make_along_axis_idx(arr_shape, indices, axis)]
def _put_along_axis_dispatcher(arr, indices, values, axis):
return (arr, indices, values)
@array_function_dispatch(_put_along_axis_dispatcher)
def put_along_axis(arr, indices, values, axis):
"""
将值插入到目标数组中,通过匹配1维索引和数据切片。
这个函数沿着指定轴迭代匹配的1维切片,使用索引数组将值放入数据数组中。这些切片可以是不同长度的。
返回沿轴产生索引的函数,如 `argsort` 和 `argpartition`,可以生成适合此函数使用的索引。
.. versionadded:: 1.15.0
Parameters
----------
arr : ndarray (Ni..., M, Nk...)
目标数组。
indices : ndarray (Ni..., J, Nk...)
要在 `arr` 的每个1维切片上更改的索引。它必须与 `arr` 的维度匹配,但 Ni 和 Nj 中的维度可以是 1,以便与 `arr` 广播。
values : array_like (Ni..., J, Nk...)
要插入到这些索引处的值。其形状和维度会广播以匹配 `indices`。
axis : int
要沿其获取1维切片的轴。如果 `axis` 是 None,则将目标数组视为其已创建的展平1维视图。
Notes
-----
这相当于(但比)`ndindex` 和 `s_` 的以下用法更快,它设置 `ii` 和 `kk` 的每个值为索引元组:
Ni, M, Nk = a.shape[:axis], a.shape[axis], a.shape[axis+1:]
J = indices.shape[axis] # 可能不等于 M
for ii in ndindex(Ni):
for kk in ndindex(Nk):
a_1d = a [ii + s_[:,] + kk]
indices_1d = indices[ii + s_[:,] + kk]
values_1d = values [ii + s_[:,] + kk]
for j in range(J):
a_1d[indices_1d[j]] = values_1d[j]
或者等效地,消除内部循环,最后两行将是:
a_1d[indices_1d] = values_1d
See Also
--------
take_along_axis :
通过匹配1维索引和数据切片从输入数组中获取值
Examples
--------
对于这个示例数组
>>> a = np.array([[10, 30, 20], [60, 40, 50]])
我们可以用以下代码将最大值替换为:
>>> ai = np.argmax(a, axis=1, keepdims=True)
>>> ai
array([[1],
[0]])
>>> np.put_along_axis(a, ai, 99, axis=1)
>>> a
array([[10, 99, 20],
[99, 40, 50]])
"""
if axis is None:
if indices.ndim != 1:
raise ValueError(
'当 `axis=None` 时,`indices` 必须具有单个维度。')
arr = arr.flat
axis = 0
arr_shape = (len(arr),)
else:
axis = normalize_axis_index(axis, arr.ndim)
arr_shape = arr.shape
arr[_make_along_axis_idx(arr_shape, indices, axis)] = values
def _apply_along_axis_dispatcher(func1d, axis, arr, *args, **kwargs):
return (arr,)
@array_function_dispatch(_apply_along_axis_dispatcher)
def apply_along_axis(func1d, axis, arr, *args, **kwargs):
"""
Apply a function to 1-D slices along the given axis.
Execute `func1d(a, *args, **kwargs)` where `func1d` operates on 1-D arrays
and `a` is a 1-D slice of `arr` along `axis`.
This is equivalent to (but faster than) the following use of `ndindex` and
`s_`, which sets each of ``ii``, ``jj``, and ``kk`` to a tuple of indices::
Ni, Nk = a.shape[:axis], a.shape[axis+1:]
for ii in ndindex(Ni):
for kk in ndindex(Nk):
f = func1d(arr[ii + s_[:,] + kk])
Nj = f.shape
for jj in ndindex(Nj):
out[ii + jj + kk] = f[jj]
Equivalently, eliminating the inner loop, this can be expressed as::
Ni, Nk = a.shape[:axis], a.shape[axis+1:]
for ii in ndindex(Ni):
for kk in ndindex(Nk):
out[ii + s_[...,] + kk] = func1d(arr[ii + s_[:,] + kk])
Parameters
----------
func1d : function (M,) -> (Nj...)
This function should accept 1-D arrays. It is applied to 1-D
slices of `arr` along the specified axis.
axis : integer
Axis along which `arr` is sliced.
arr : ndarray (Ni..., M, Nk...)
Input array.
args : any
Additional arguments to `func1d`.
kwargs : any
Additional named arguments to `func1d`.
.. versionadded:: 1.9.0
Returns
-------
out : ndarray (Ni..., Nj..., Nk...)
The output array. The shape of `out` is identical to the shape of
`arr`, except along the `axis` dimension. This axis is removed, and
replaced with new dimensions equal to the shape of the return value
of `func1d`. So if `func1d` returns a scalar `out` will have one
fewer dimensions than `arr`.
See Also
--------
apply_over_axes : Apply a function repeatedly over multiple axes.
Examples
--------
>>> def my_func(a):
... \"\"\"Average first and last element of a 1-D array\"\"\"
... return (a[0] + a[-1]) * 0.5
>>> b = np.array([[1,2,3], [4,5,6], [7,8,9]])
>>> np.apply_along_axis(my_func, 0, b)
array([4., 5., 6.])
>>> np.apply_along_axis(my_func, 1, b)
array([2., 5., 8.])
For a function that returns a 1D array, the number of dimensions in
`outarr` is the same as `arr`.
>>> b = np.array([[8,1,7], [4,3,9], [5,2,6]])
>>> np.apply_along_axis(sorted, 1, b)
array([[1, 7, 8],
[3, 4, 9],
[2, 5, 6]])
For a function that returns a higher dimensional array, those dimensions
are inserted in place of the `axis` dimension.
>>> b = np.array([[1,2,3], [4,5,6], [7,8,9]])
>>> np.apply_along_axis(np.diag, -1, b)
"""
array([[[1, 0, 0],
[0, 2, 0],
[0, 0, 3]],
[[4, 0, 0],
[0, 5, 0],
[0, 0, 6]],
[[7, 0, 0],
[0, 8, 0],
[0, 0, 9]]])
"""
# 处理负轴索引
conv = _array_converter(arr)
# 将处理后的数组赋值给arr
arr = conv[0]
# 获取数组的维度
nd = arr.ndim
# 规范化轴索引,确保axis在有效范围内
axis = normalize_axis_index(axis, nd)
# 将迭代轴放置在数组维度的末尾
in_dims = list(range(nd))
inarr_view = transpose(arr, in_dims[:axis] + in_dims[axis+1:] + [axis])
# 计算迭代轴的索引,并在末尾添加省略号,以防止0维数组退化为标量,从而修复gh-8642
inds = ndindex(inarr_view.shape[:-1])
inds = (ind + (Ellipsis,) for ind in inds)
# 在第一个项目上调用函数
try:
ind0 = next(inds)
except StopIteration:
raise ValueError(
'Cannot apply_along_axis when any iteration dimensions are 0'
) from None
# 对inarr_view[ind0]应用func1d函数,*args和**kwargs是可选的额外参数
res = asanyarray(func1d(inarr_view[ind0], *args, **kwargs))
# 构建一个缓冲区用于存储func1d的评估结果。
# 删除请求的轴,并在末尾添加新的轴,使得每次写操作都是连续的。
if not isinstance(res, matrix):
buff = zeros_like(res, shape=inarr_view.shape[:-1] + res.shape)
else:
# 矩阵在重塑时可能会出现问题,所以这里不保留它们。
buff = zeros(inarr_view.shape[:-1] + res.shape, dtype=res.dtype)
# 轴的排列,以便out = buff.transpose(buff_permute)
buff_dims = list(range(buff.ndim))
buff_permute = (
buff_dims[0 : axis] +
buff_dims[buff.ndim-res.ndim : buff.ndim] +
buff_dims[axis : buff.ndim-res.ndim]
)
# 保存第一个结果,然后计算并保存所有剩余结果
buff[ind0] = res
for ind in inds:
buff[ind] = asanyarray(func1d(inarr_view[ind], *args, **kwargs))
# 对buff进行转置,使用buff_permute重新排列轴,得到最终结果res
res = transpose(buff, buff_permute)
# 将结果进行包装并返回
return conv.wrap(res)
# 用于分发给定函数的轴参数,返回输入数组 `a` 的元组
def _apply_over_axes_dispatcher(func, a, axes):
return (a,)
# 应用函数到多个轴上的分发器装饰器
@array_function_dispatch(_apply_over_axes_dispatcher)
def apply_over_axes(func, a, axes):
"""
Apply a function repeatedly over multiple axes.
`func` is called as `res = func(a, axis)`, where `axis` is the first
element of `axes`. The result `res` of the function call must have
either the same dimensions as `a` or one less dimension. If `res`
has one less dimension than `a`, a dimension is inserted before
`axis`. The call to `func` is then repeated for each axis in `axes`,
with `res` as the first argument.
Parameters
----------
func : function
This function must take two arguments, `func(a, axis)`.
a : array_like
Input array.
axes : array_like
Axes over which `func` is applied; the elements must be integers.
Returns
-------
apply_over_axis : ndarray
The output array. The number of dimensions is the same as `a`,
but the shape can be different. This depends on whether `func`
changes the shape of its output with respect to its input.
See Also
--------
apply_along_axis :
Apply a function to 1-D slices of an array along the given axis.
Notes
-----
This function is equivalent to tuple axis arguments to reorderable ufuncs
with keepdims=True. Tuple axis arguments to ufuncs have been available since
version 1.7.0.
Examples
--------
>>> a = np.arange(24).reshape(2,3,4)
>>> a
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],
[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
Sum over axes 0 and 2. The result has same number of dimensions
as the original array:
>>> np.apply_over_axes(np.sum, a, [0,2])
array([[[ 60],
[ 92],
[124]]])
Tuple axis arguments to ufuncs are equivalent:
>>> np.sum(a, axis=(0,2), keepdims=True)
array([[[ 60],
[ 92],
[124]]])
"""
# 将输入数组 `a` 转换为 ndarray 类型
val = asarray(a)
# 获取输入数组 `a` 的维度数
N = a.ndim
# 如果轴参数 `axes` 的维度为0,则转换为元组
if array(axes).ndim == 0:
axes = (axes,)
# 遍历每个轴参数 `axes` 中的轴
for axis in axes:
# 如果轴为负数,将其转换为对应的非负数索引
if axis < 0:
axis = N + axis
# 构造函数调用的参数元组
args = (val, axis)
# 调用给定函数 `func`,将结果保存为 `res`
res = func(*args)
# 如果结果 `res` 的维度与输入数组 `val` 的维度相同,则更新 `val`
if res.ndim == val.ndim:
val = res
# 否则,在指定轴前插入新维度,并更新 `val`
else:
res = expand_dims(res, axis)
# 如果插入新维度后 `res` 的维度与输入数组 `val` 的维度相同,则更新 `val`
if res.ndim == val.ndim:
val = res
# 否则,抛出值错误,指示函数未返回正确形状的数组
else:
raise ValueError("function is not returning "
"an array of the correct shape")
# 返回最终处理结果 `val`
return val
# 用于分发给定数组和轴参数的装饰器,返回输入数组 `a` 的元组
def _expand_dims_dispatcher(a, axis):
return (a,)
# 插入新轴以扩展数组形状的函数
@array_function_dispatch(_expand_dims_dispatcher)
def expand_dims(a, axis):
"""
Expand the shape of an array.
Insert a new axis that will appear at the `axis` position in the expanded
array shape.
Parameters
----------
a : array_like
Input array.
"""
# 如果输入的数组 `a` 是矩阵类型,将其转换为 ndarray 类型
if isinstance(a, matrix):
a = asarray(a)
else:
# 否则,将输入的数组 `a` 转换为任意数组类型
a = asanyarray(a)
# 如果输入的轴 `axis` 不是 tuple 或者 list 类型,转换为 tuple 类型
if type(axis) not in (tuple, list):
axis = (axis,)
# 计算输出数组的维度,为输入数组的维度加上 `axis` 的长度
out_ndim = len(axis) + a.ndim
# 根据输入的轴 `axis` 和输出的维度 `out_ndim`,规范化轴元组
axis = normalize_axis_tuple(axis, out_ndim)
# 创建一个迭代器用于输入数组 `a` 的形状
shape_it = iter(a.shape)
# 根据输入的轴 `axis` 和输出的维度 `out_ndim`,生成输出数组的形状
shape = [1 if ax in axis else next(shape_it) for ax in range(out_ndim)]
# 将输入数组 `a` 按照生成的形状 `shape` 进行重塑,并返回结果
return a.reshape(shape)
# NOTE: Remove once deprecation period passes
# 设置模块为 "numpy",这在 NumPy 中用于一些内部操作
@set_module("numpy")
# 定义函数 `row_stack`,用于堆叠数组的行,已被弃用,将在 NumPy 2.0 中删除,预计在 2023-08-18 弃用
def row_stack(tup, *, dtype=None, casting="same_kind"):
# 发出警告,提示用户 `row_stack` 已弃用,建议直接使用 `np.vstack`
warnings.warn(
"`row_stack` alias is deprecated. "
"Use `np.vstack` directly.",
DeprecationWarning,
stacklevel=2
)
# 调用 `vstack` 函数进行实际的堆叠操作
return vstack(tup, dtype=dtype, casting=casting)
# 将 `row_stack` 函数的文档字符串设置为 `vstack` 函数的文档字符串
row_stack.__doc__ = vstack.__doc__
# 定义 `_column_stack_dispatcher` 函数,用于分派给 `_arrays_for_stack_dispatcher` 函数
def _column_stack_dispatcher(tup):
return _arrays_for_stack_dispatcher(tup)
# 使用 `array_function_dispatch` 装饰器,定义 `column_stack` 函数
@array_function_dispatch(_column_stack_dispatcher)
# `column_stack` 函数用于将多个一维数组或二维数组按列堆叠成二维数组
def column_stack(tup):
"""
Stack 1-D arrays as columns into a 2-D array.
Take a sequence of 1-D arrays and stack them as columns
to make a single 2-D array. 2-D arrays are stacked as-is,
just like with `hstack`. 1-D arrays are turned into 2-D columns
first.
Parameters
----------
tup : sequence of 1-D or 2-D arrays.
Arrays to stack. All of them must have the same first dimension.
Returns
-------
stacked : 2-D array
The array formed by stacking the given arrays.
See Also
--------
stack, hstack, vstack, concatenate
Examples
--------
>>> a = np.array((1,2,3))
>>> b = np.array((2,3,4))
>>> np.column_stack((a,b))
array([[1, 2],
[2, 3],
[3, 4]])
"""
arrays = []
# 遍历输入的数组序列
for v in tup:
# 将每个元素转换为数组对象
arr = asanyarray(v)
# 如果数组的维度小于 2,则将其转置为二维数组的列
if arr.ndim < 2:
arr = array(arr, copy=None, subok=True, ndmin=2).T
# 将处理后的数组添加到数组列表中
arrays.append(arr)
# 使用 `_nx.concatenate` 函数在第二维度上连接所有数组,形成最终的堆叠数组
return _nx.concatenate(arrays, 1)
# 定义 `_dstack_dispatcher` 函数,用于分派给 `_arrays_for_stack_dispatcher` 函数
def _dstack_dispatcher(tup):
return _arrays_for_stack_dispatcher(tup)
# 使用 `array_function_dispatch` 装饰器,定义 `dstack` 函数
@array_function_dispatch(_dstack_dispatcher)
# `dstack` 函数用于沿着第三个轴(深度方向)堆叠数组序列
def dstack(tup):
"""
Stack arrays in sequence depth wise (along third axis).
This is equivalent to concatenation along the third axis after 2-D arrays
of shape `(M,N)` have been reshaped to `(M,N,1)` and 1-D arrays of shape
`(N,)` have been reshaped to `(1,N,1)`. Rebuilds arrays divided by
`dsplit`.
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). The functions `concatenate`, `stack` and
`block` provide more general stacking and concatenation operations.
Parameters
----------
tup : sequence of arrays
The arrays must have the same shape along all but the third axis.
1-D or 2-D arrays must have the same shape.
Returns
-------
stacked : ndarray
The array formed by stacking the given arrays, will be at least 3-D.
See Also
--------
concatenate : Join a sequence of arrays along an existing axis.
stack : Join a sequence of arrays along a new axis.
block : Assemble an nd-array from nested lists of blocks.
vstack : Stack arrays in sequence vertically (row wise).
hstack : Stack arrays in sequence horizontally (column wise).
"""
# 为了深度堆叠,将每个数组扩展到至少三维,然后沿第三个轴连接它们
return concatenate([atleast_3d(_m) for _m in tup], axis=2)
# column_stack函数:将多个一维数组按列堆叠成一个二维数组。
# dsplit函数:沿着第三个轴(即深度方向)分割数组。
Examples
--------
>>> a = np.array((1,2,3))
>>> b = np.array((2,3,4))
>>> np.dstack((a,b))
array([[[1, 2],
[2, 3],
[3, 4]]])
>>> a = np.array([[1],[2],[3]])
>>> b = np.array([[2],[3],[4]])
>>> np.dstack((a,b))
array([[[1, 2]],
[[2, 3]],
[[3, 4]]])
"""
arrs = atleast_3d(*tup)
if not isinstance(arrs, tuple):
arrs = (arrs,)
return _nx.concatenate(arrs, 2)
def _replace_zero_by_x_arrays(sub_arys):
for i in range(len(sub_arys)):
if _nx.ndim(sub_arys[i]) == 0:
sub_arys[i] = _nx.empty(0, dtype=sub_arys[i].dtype)
elif _nx.sometrue(_nx.equal(_nx.shape(sub_arys[i]), 0)):
sub_arys[i] = _nx.empty(0, dtype=sub_arys[i].dtype)
return sub_arys
def _array_split_dispatcher(ary, indices_or_sections, axis=None):
return (ary, indices_or_sections)
@array_function_dispatch(_array_split_dispatcher)
def array_split(ary, indices_or_sections, axis=0):
"""
将数组分割成多个子数组。
请参考“split”文档。这两个函数之间唯一的区别在于,
“array_split”允许“indices_or_sections”是一个整数,而不需要等分轴。
对于长度为l的数组,应该分割为n个部分,它返回l % n个大小为l//n + 1的子数组,
和其余大小为l//n的子数组。
参见
--------
split : 将数组等分成多个子数组。
示例
--------
>>> x = np.arange(8.0)
>>> np.array_split(x, 3)
[array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7.])]
>>> x = np.arange(9)
>>> np.array_split(x, 4)
[array([0, 1, 2]), array([3, 4]), array([5, 6]), array([7, 8])]
"""
try:
Ntotal = ary.shape[axis]
except AttributeError:
Ntotal = len(ary)
try:
Nsections = len(indices_or_sections) + 1
div_points = [0] + list(indices_or_sections) + [Ntotal]
except TypeError:
Nsections = int(indices_or_sections)
if Nsections <= 0:
raise ValueError('number sections must be larger than 0.') from None
Neach_section, extras = divmod(Ntotal, Nsections)
section_sizes = ([0] +
extras * [Neach_section+1] +
(Nsections-extras) * [Neach_section])
div_points = _nx.array(section_sizes, dtype=_nx.intp).cumsum()
sub_arys = []
sary = _nx.swapaxes(ary, axis, 0)
for i in range(Nsections):
st = div_points[i]
end = div_points[i + 1]
sub_arys.append(_nx.swapaxes(sary[st:end], axis, 0))
return sub_arys
def _split_dispatcher(ary, indices_or_sections, axis=None):
return (ary, indices_or_sections)
@array_function_dispatch(_split_dispatcher)
def split(ary, indices_or_sections, axis=0):
"""
将数组分割成多个作为视图的子数组。
参数
----------
ary : ndarray
要分割成子数组的数组。
try:
# 尝试获取 `indices_or_sections` 的长度,如果无法获取则抛出 TypeError 异常
len(indices_or_sections)
except TypeError:
# 如果无法获取长度,说明 `indices_or_sections` 是一个整数,将其作为 `sections`
sections = indices_or_sections
# 获取数组 `ary` 在指定轴 `axis` 上的长度
N = ary.shape[axis]
# 如果数组长度不能被 `sections` 整除,抛出 ValueError 异常
if N % sections:
raise ValueError(
'array split does not result in an equal division') from None
# 调用 `array_split` 函数进行数组分割,并返回分割后的结果
return array_split(ary, indices_or_sections, axis)
# 定义一个分发函数,用于处理 hsplit 和 vsplit 函数的分派逻辑
def _hvdsplit_dispatcher(ary, indices_or_sections):
return (ary, indices_or_sections)
# 使用装饰器将 _hvdsplit_dispatcher 注册为 hsplit 函数的分发函数
@array_function_dispatch(_hvdsplit_dispatcher)
def hsplit(ary, indices_or_sections):
"""
将数组沿水平方向(列方向)分割为多个子数组。
请参考 `split` 的文档。`hsplit` 相当于 `split`,其中 ``axis=1``,
数组始终沿第二轴分割,对于 1-D 数组,则在 ``axis=0`` 处分割。
See Also
--------
split : 将数组分割为多个等大小的子数组。
Examples
--------
>>> 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.]])
>>> 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)]
对于更高维度的数组,分割仍沿第二轴进行。
>>> x = np.arange(8.0).reshape(2, 2, 2)
>>> x
array([[[0., 1.],
[2., 3.]],
[[4., 5.],
[6., 7.]]])
>>> np.hsplit(x, 2)
[array([[[0., 1.]],
[[4., 5.]]]),
array([[[2., 3.]],
[[6., 7.]]])]
对于 1-D 数组,分割沿轴 0 进行。
>>> x = np.array([0, 1, 2, 3, 4, 5])
>>> np.hsplit(x, 2)
[array([0, 1, 2]), array([3, 4, 5])]
"""
# 如果数组维度为 0,则引发错误,hsplit 只适用于至少 1 维的数组
if _nx.ndim(ary) == 0:
raise ValueError('hsplit only works on arrays of 1 or more dimensions')
# 如果数组维度大于 1,则使用 split 函数在第二轴(axis=1)进行分割
if ary.ndim > 1:
return split(ary, indices_or_sections, 1)
else:
# 对于 1-D 数组,使用 split 函数在轴 0 进行分割
return split(ary, indices_or_sections, 0)
# 使用装饰器将 _hvdsplit_dispatcher 注册为 vsplit 函数的分发函数
@array_function_dispatch(_hvdsplit_dispatcher)
def vsplit(ary, indices_or_sections):
"""
将数组沿垂直方向(行方向)分割为多个子数组。
请参考 `split` 的文档。`vsplit` 相当于 `split`,其中 `axis=0`(默认),
数组始终沿第一轴进行分割,无论数组的维度如何。
See Also
--------
split : 将数组分割为多个等大小的子数组。
Examples
--------
>>> 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.]])
>>> 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, 6]))
"""
# vsplit 与 hsplit 类似,但始终在第一轴(axis=0)进行分割
return split(ary, indices_or_sections, 0)
[array([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]]),
array([[12., 13., 14., 15.]]),
array([], shape=(0, 4), dtype=float64)]
With a higher dimensional array the split is still along the first axis.
>>> x = np.arange(8.0).reshape(2, 2, 2)
>>> x
array([[[0., 1.],
[2., 3.]],
[[4., 5.],
[6., 7.]]])
>>> np.vsplit(x, 2)
[array([[[0., 1.],
[2., 3.]]]),
array([[[4., 5.],
[6., 7.]]])]
"""
if _nx.ndim(ary) < 2:
raise ValueError('vsplit only works on arrays of 2 or more dimensions')
return split(ary, indices_or_sections, 0)
@array_function_dispatch(_hvdsplit_dispatcher)
def dsplit(ary, indices_or_sections):
"""
Split array into multiple sub-arrays along the 3rd axis (depth).
Please refer to the `split` documentation. `dsplit` is equivalent
to `split` with ``axis=2``, the array is always split along the third
axis provided the array dimension is greater than or equal to 3.
See Also
--------
split : Split an array into multiple sub-arrays of equal size.
Examples
--------
>>> x = np.arange(16.0).reshape(2, 2, 4)
>>> x
array([[[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.]],
[[ 8., 9., 10., 11.],
[12., 13., 14., 15.]]])
>>> np.dsplit(x, 2)
[array([[[ 0., 1.],
[ 4., 5.]],
[[ 8., 9.],
[12., 13.]]]), array([[[ 2., 3.],
[ 6., 7.]],
[[10., 11.],
[14., 15.]]])]
>>> np.dsplit(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=(2, 2, 0), dtype=float64)]
"""
if _nx.ndim(ary) < 3:
raise ValueError('dsplit only works on arrays of 3 or more dimensions')
return split(ary, indices_or_sections, 2)
def get_array_wrap(*args):
"""Find the wrapper for the array with the highest priority.
In case of ties, leftmost wins. If no wrapper is found, return None.
.. deprecated:: 2.0
"""
warnings.warn(
"`get_array_wrap` is deprecated. "
"(deprecated in NumPy 2.0)",
DeprecationWarning,
stacklevel=2
)
wrappers = sorted((getattr(x, '__array_priority__', 0), -i,
x.__array_wrap__) for i, x in enumerate(args)
if hasattr(x, '__array_wrap__'))
if wrappers:
return wrappers[-1][-1]
return None
def _kron_dispatcher(a, b):
return (a, b)
@array_function_dispatch(_kron_dispatcher)
def kron(a, b):
"""
Kronecker product of two arrays.
Computes the Kronecker product, a composite array made of blocks of the
second array scaled by the first.
Parameters
----------
a, b : array_like
Returns
-------
out : ndarray
See Also
--------
outer : The outer product
Notes
-----
The function assumes that the number of dimensions of `a` and `b`
are the same, if necessary prepending the smallest with ones.
If ``a.shape = (r0,r1,..,rN)`` and ``b.shape = (s0,s1,...,sN)``,
the Kronecker product has shape ``(r0*s0, r1*s1, ..., rN*SN)``.
The elements are products of elements from `a` and `b`, organized
explicitly by::
kron(a,b)[k0,k1,...,kN] = a[i0,i1,...,iN] * b[j0,j1,...,jN]
where::
kt = it * st + jt, t = 0,...,N
"""
return _multiarray_umath.c_kron(a, b)
"""
In the common 2-D case (N=1), the block structure can be visualized::
[[ a[0,0]*b, a[0,1]*b, ... , a[0,-1]*b ],
[ ... ... ],
[ a[-1,0]*b, a[-1,1]*b, ... , a[-1,-1]*b ]]
Examples
--------
>>> np.kron([1,10,100], [5,6,7])
array([ 5, 6, 7, ..., 500, 600, 700])
>>> np.kron([5,6,7], [1,10,100])
array([ 5, 50, 500, ..., 7, 70, 700])
>>> np.kron(np.eye(2), np.ones((2,2)))
array([[1., 1., 0., 0.],
[1., 1., 0., 0.],
[0., 0., 1., 1.],
[0., 0., 1., 1.]])
>>> a = np.arange(100).reshape((2,5,2,5))
>>> b = np.arange(24).reshape((2,3,4))
>>> c = np.kron(a,b)
>>> c.shape
(2, 10, 6, 20)
>>> I = (1,3,0,2)
>>> J = (0,2,1)
>>> J1 = (0,) + J # extend to ndim=4
>>> S1 = (1,) + b.shape
>>> K = tuple(np.array(I) * np.array(S1) + np.array(J1))
>>> c[K] == a[I]*b[J]
True
"""
b = asanyarray(b)
a = array(a, copy=None, subok=True, ndmin=b.ndim)
is_any_mat = isinstance(a, matrix) or isinstance(b, matrix)
ndb, nda = b.ndim, a.ndim
nd = max(ndb, nda)
if (nda == 0 or ndb == 0):
return _nx.multiply(a, b)
as_ = a.shape
bs = b.shape
if not a.flags.contiguous:
a = reshape(a, as_)
if not b.flags.contiguous:
b = reshape(b, bs)
as_ = (1,)*max(0, ndb-nda) + as_
bs = (1,)*max(0, nda-ndb) + bs
a_arr = expand_dims(a, axis=tuple(range(ndb-nda)))
b_arr = expand_dims(b, axis=tuple(range(nda-ndb)))
a_arr = expand_dims(a_arr, axis=tuple(range(1, nd*2, 2)))
b_arr = expand_dims(b_arr, axis=tuple(range(0, nd*2, 2)))
result = _nx.multiply(a_arr, b_arr, subok=(not is_any_mat))
result = result.reshape(_nx.multiply(as_, bs))
return result if not is_any_mat else matrix(result, copy=False)
def _tile_dispatcher(A, reps):
return (A, reps)
@array_function_dispatch(_tile_dispatcher)
def tile(A, reps):
"""
Construct an array by repeating A the number of times given by reps.
If `reps` has length ``d``, the result will have dimension of
``max(d, A.ndim)``.
If ``A.ndim < d``, `A` is promoted to be d-dimensional by prepending new
axes. So a shape (3,) array is promoted to (1, 3) for 2-D replication,
or shape (1, 1, 3) for 3-D replication. If this is not the desired
behavior, promote `A` to d-dimensions manually before calling this
function.
If ``A.ndim > d``, `reps` is promoted to `A`.ndim by prepending 1's to it.
Thus for an `A` of shape (2, 3, 4, 5), a `reps` of (2, 2) is treated as
(1, 1, 2, 2).
Note : Although tile may be used for broadcasting, it is strongly
recommended to use numpy's broadcasting operations and functions.
Parameters
----------
A : array_like
The input array.
reps : array_like
The number of repetitions of `A` along each axis.
Returns
-------
c : ndarray
The tiled output array.
See Also
--------
repeat : Repeat elements of an array.
broadcast_to : Broadcast an array to a new shape
Examples
--------
>>> a = np.array([0, 1, 2])
>>> np.tile(a, 2)
array([0, 1, 2, 0, 1, 2])
>>> np.tile(a, (2, 2))
array([[0, 1, 2, 0, 1, 2],
[0, 1, 2, 0, 1, 2]])
>>> np.tile(a, (2, 1, 2))
array([[[0, 1, 2, 0, 1, 2]],
[[0, 1, 2, 0, 1, 2]]])
>>> b = np.array([[1, 2], [3, 4]])
>>> np.tile(b, 2)
array([[1, 2, 1, 2],
[3, 4, 3, 4]])
>>> np.tile(b, (2, 1))
array([[1, 2],
[3, 4],
[1, 2],
[3, 4]])
>>> c = np.array([1,2,3,4])
>>> np.tile(c,(4,1))
array([[1, 2, 3, 4],
[1, 2, 3, 4],
[1, 2, 3, 4],
[1, 2, 3, 4]])
"""
try:
tup = tuple(reps)
except TypeError:
tup = (reps,)
d = len(tup)
if all(x == 1 for x in tup) and isinstance(A, _nx.ndarray):
return _nx.array(A, copy=True, subok=True, ndmin=d)
else:
c = _nx.array(A, copy=None, subok=True, ndmin=d)
if (d < c.ndim):
tup = (1,)*(c.ndim-d) + tup
shape_out = tuple(s*t for s, t in zip(c.shape, tup))
n = c.size
if n > 0:
for dim_in, nrep in zip(c.shape, tup):
if nrep != 1:
c = c.reshape(-1, n).repeat(nrep, 0)
n //= dim_in
return c.reshape(shape_out)
.\numpy\numpy\lib\_shape_base_impl.pyi
import sys
from collections.abc import Callable, Sequence
from typing import TypeVar, Any, overload, SupportsIndex, Protocol
if sys.version_info >= (3, 10):
from typing import ParamSpec, Concatenate
else:
from typing_extensions import ParamSpec, Concatenate
import numpy as np
from numpy import (
generic,
integer,
ufunc,
unsignedinteger,
signedinteger,
floating,
complexfloating,
object_,
)
from numpy._typing import (
ArrayLike,
NDArray,
_ShapeLike,
_ArrayLike,
_ArrayLikeBool_co,
_ArrayLikeUInt_co,
_ArrayLikeInt_co,
_ArrayLikeFloat_co,
_ArrayLikeComplex_co,
_ArrayLikeObject_co,
)
from numpy._core.shape_base import vstack
_P = ParamSpec("_P")
_SCT = TypeVar("_SCT", bound=generic)
class _ArrayWrap(Protocol):
def __call__(
self,
array: NDArray[Any],
context: None | tuple[ufunc, tuple[Any, ...], int] = ...,
return_scalar: bool = ...,
/,
) -> Any: ...
class _SupportsArrayWrap(Protocol):
@property
def __array_wrap__(self) -> _ArrayWrap: ...
__all__: list[str]
def take_along_axis(
arr: _SCT | NDArray[_SCT],
indices: NDArray[integer[Any]],
axis: None | int,
) -> NDArray[_SCT]: ...
def put_along_axis(
arr: NDArray[_SCT],
indices: NDArray[integer[Any]],
values: ArrayLike,
axis: None | int,
) -> None: ...
@overload
def apply_along_axis(
func1d: Callable[Concatenate[NDArray[Any], _P], _ArrayLike[_SCT]],
axis: SupportsIndex,
arr: ArrayLike,
*args: _P.args,
**kwargs: _P.kwargs,
) -> NDArray[_SCT]: ...
@overload
def apply_along_axis(
func1d: Callable[Concatenate[NDArray[Any], _P], ArrayLike],
axis: SupportsIndex,
arr: ArrayLike,
*args: _P.args,
**kwargs: _P.kwargs,
) -> NDArray[Any]: ...
def apply_over_axes(
func: Callable[[NDArray[Any], int], NDArray[_SCT]],
a: ArrayLike,
axes: int | Sequence[int],
) -> NDArray[_SCT]: ...
@overload
def expand_dims(
a: _ArrayLike[_SCT],
axis: _ShapeLike,
) -> NDArray[_SCT]: ...
@overload
def expand_dims(
a: ArrayLike,
axis: _ShapeLike,
) -> NDArray[Any]: ...
@overload
def column_stack(tup: Sequence[_ArrayLike[_SCT]]) -> NDArray[_SCT]: ...
@overload
def column_stack(tup: Sequence[ArrayLike]) -> NDArray[Any]: ...
@overload
def dstack(tup: Sequence[_ArrayLike[_SCT]]) -> NDArray[_SCT]: ...
@overload
def dstack(tup: Sequence[ArrayLike]) -> NDArray[Any]: ...
@overload
def array_split(
ary: _ArrayLike[_SCT],
indices_or_sections: _ShapeLike,
axis: SupportsIndex = ...,
) -> list[NDArray[_SCT]]: ...
@overload
def array_split(
ary: ArrayLike,
indices_or_sections: _ShapeLike,
axis: SupportsIndex = ...,
) -> list[NDArray[Any]]: ...
@overload
def split(
ary: _ArrayLike[_SCT],
indices_or_sections: _ShapeLike,
axis: SupportsIndex = ...,
) -> list[NDArray[_SCT]]: ...
@overload
def split(
ary: ArrayLike,
indices_or_sections: _ShapeLike,
axis: SupportsIndex = ...,
indices_or_sections: _ShapeLike,
axis: SupportsIndex = ...,
) -> list[NDArray[Any]]: ...
@overload
def hsplit(
ary: _ArrayLike[_SCT],
indices_or_sections: _ShapeLike,
) -> list[NDArray[_SCT]]: ...
@overload
def hsplit(
ary: ArrayLike,
indices_or_sections: _ShapeLike,
) -> list[NDArray[Any]]: ...
@overload
def vsplit(
ary: _ArrayLike[_SCT],
indices_or_sections: _ShapeLike,
) -> list[NDArray[_SCT]]: ...
@overload
def vsplit(
ary: ArrayLike,
indices_or_sections: _ShapeLike,
) -> list[NDArray[Any]]: ...
@overload
def dsplit(
ary: _ArrayLike[_SCT],
indices_or_sections: _ShapeLike,
) -> list[NDArray[_SCT]]: ...
@overload
def dsplit(
ary: ArrayLike,
indices_or_sections: _ShapeLike,
) -> list[NDArray[Any]]: ...
@overload
def get_array_wrap(*args: _SupportsArrayWrap) -> _ArrayWrap: ...
@overload
def get_array_wrap(*args: object) -> None | _ArrayWrap: ...
@overload
def kron(a: _ArrayLikeBool_co, b: _ArrayLikeBool_co) -> NDArray[np.bool]: ...
@overload
def kron(a: _ArrayLikeUInt_co, b: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ...
@overload
def kron(a: _ArrayLikeInt_co, b: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ...
@overload
def kron(a: _ArrayLikeFloat_co, b: _ArrayLikeFloat_co) -> NDArray[floating[Any]]: ...
@overload
def kron(a: _ArrayLikeComplex_co, b: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...
@overload
def kron(a: _ArrayLikeObject_co, b: Any) -> NDArray[object_]: ...
@overload
def kron(a: Any, b: _ArrayLikeObject_co) -> NDArray[object_]: ...
@overload
def tile(
A: _ArrayLike[_SCT],
reps: int | Sequence[int],
) -> NDArray[_SCT]: ...
@overload
def tile(
A: ArrayLike,
reps: int | Sequence[int],
) -> NDArray[Any]: ...
.\numpy\numpy\lib\_stride_tricks_impl.py
"""
Utilities that manipulate strides to achieve desirable effects.
An explanation of strides can be found in the :ref:`arrays.ndarray`.
Functions
---------
.. autosummary::
:toctree: generated/
"""
import numpy as np
from numpy._core.numeric import normalize_axis_tuple
from numpy._core.overrides import array_function_dispatch, set_module
__all__ = ['broadcast_to', 'broadcast_arrays', 'broadcast_shapes']
class DummyArray:
"""Dummy object that just exists to hang __array_interface__ dictionaries
and possibly keep alive a reference to a base array.
"""
def __init__(self, interface, base=None):
self.__array_interface__ = interface
self.base = base
def _maybe_view_as_subclass(original_array, new_array):
if type(original_array) is not type(new_array):
new_array = new_array.view(type=type(original_array))
if new_array.__array_finalize__:
new_array.__array_finalize__(original_array)
return new_array
@set_module("numpy.lib.stride_tricks")
def as_strided(x, shape=None, strides=None, subok=False, writeable=True):
"""
Create a view into the array with the given shape and strides.
.. warning:: This function has to be used with extreme care, see notes.
Parameters
----------
x : ndarray
Array to create a new.
shape : sequence of int, optional
The shape of the new array. Defaults to ``x.shape``.
strides : sequence of int, optional
The strides of the new array. Defaults to ``x.strides``.
subok : bool, optional
.. versionadded:: 1.10
If True, subclasses are preserved.
writeable : bool, optional
.. versionadded:: 1.12
If set to False, the returned array will always be readonly.
Otherwise it will be writable if the original array was. It
is advisable to set this to False if possible (see Notes).
Returns
-------
view : ndarray
See also
--------
broadcast_to : broadcast an array to a given shape.
reshape : reshape an array.
lib.stride_tricks.sliding_window_view :
userfriendly and safe function for a creation of sliding window views.
Notes
-----
``as_strided`` creates a view into the array given the exact strides
and shape. This means it manipulates the internal data structure of
ndarray and, if done incorrectly, the array elements can point to
invalid memory and can corrupt results or crash your program.
It is advisable to always use the original ``x.strides`` when
calculating new strides to avoid reliance on a contiguous memory
layout.
"""
shape = x.shape if shape is None else shape
strides = x.strides if strides is None else strides
return np.lib.stride_tricks.as_strided(x, shape=shape, strides=strides, subok=subok, writeable=writeable)
"""
Furthermore, arrays created with this function often contain self
overlapping memory, so that two elements are identical.
Vectorized write operations on such arrays will typically be
unpredictable. They may even give different results for small, large,
or transposed arrays.
Since writing to these arrays has to be tested and done with great
care, you may want to use ``writeable=False`` to avoid accidental write
operations.
For these reasons it is advisable to avoid ``as_strided`` when
possible.
"""
x = np.array(x, copy=None, subok=subok)
interface = dict(x.__array_interface__)
if shape is not None:
interface['shape'] = tuple(shape)
if strides is not None:
interface['strides'] = tuple(strides)
array = np.asarray(DummyArray(interface, base=x))
array.dtype = x.dtype
view = _maybe_view_as_subclass(x, array)
if view.flags.writeable and not writeable:
view.flags.writeable = False
return view
def _sliding_window_view_dispatcher(x, window_shape, axis=None, *,
subok=None, writeable=None):
return (x,)
@array_function_dispatch(
_sliding_window_view_dispatcher, module="numpy.lib.stride_tricks"
)
def sliding_window_view(x, window_shape, axis=None, *,
subok=False, writeable=False):
"""
Create a sliding window view into the array with the given window shape.
Also known as rolling or moving window, the window slides across all
dimensions of the array and extracts subsets of the array at all window
positions.
.. versionadded:: 1.20.0
Parameters
----------
x : array_like
Array to create the sliding window view from.
window_shape : int or tuple of int
Size of window over each axis that takes part in the sliding window.
If `axis` is not present, must have same length as the number of input
array dimensions. Single integers `i` are treated as if they were the
tuple `(i,)`.
axis : int or tuple of int, optional
Axis or axes along which the sliding window is applied.
By default, the sliding window is applied to all axes and
`window_shape[i]` will refer to axis `i` of `x`.
If `axis` is given as a `tuple of int`, `window_shape[i]` will refer to
the axis `axis[i]` of `x`.
Single integers `i` are treated as if they were the tuple `(i,)`.
subok : bool, optional
If True, sub-classes will be passed-through, otherwise the returned
array will be forced to be a base-class array (default).
writeable : bool, optional
When true, allow writing to the returned view. The default is false,
as this should be used with caution: the returned view contains the
same memory location multiple times, so writing to one location will
cause others to change.
Returns
-------
view : ndarray
Sliding window view of the array. The sliding window dimensions are
inserted at the end, and the original dimensions are trimmed as
required by the size of the sliding window.
That is, ``view.shape = x_shape_trimmed + window_shape``, where
``x_shape_trimmed`` is ``x.shape`` with every entry reduced by one less
than the corresponding window size.
See Also
--------
lib.stride_tricks.as_strided: A lower-level and less safe routine for
creating arbitrary views from custom shape and strides.
broadcast_to: broadcast an array to a given shape.
Notes
-----
For many applications using a sliding window view can be convenient, but
potentially very slow. Often specialized solutions exist, for example:
- `scipy.signal.fftconvolve`
- filtering functions in `scipy.ndimage`
- moving window functions provided by
`bottleneck <https://github.com/pydata/bottleneck>`_.
"""
return np.lib.stride_tricks.sliding_window_view(x, window_shape, axis, subok=subok, writeable=writeable)
"""
As a rough estimate, a sliding window approach with an input size of `N`
and a window size of `W` will scale as `O(N*W)` where frequently a special
algorithm can achieve `O(N)`. That means that the sliding window variant
for a window size of 100 can be a 100 times slower than a more specialized
version.
Nevertheless, for small window sizes, when no custom algorithm exists, or
as a prototyping and developing tool, this function can be a good solution.
Examples
--------
>>> from numpy.lib.stride_tricks import sliding_window_view
>>> x = np.arange(6)
>>> x.shape
(6,)
>>> v = sliding_window_view(x, 3)
>>> v.shape
(4, 3)
>>> v
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5]])
This also works in more dimensions, e.g.
>>> i, j = np.ogrid[:3, :4]
>>> x = 10*i + j
>>> x.shape
(3, 4)
>>> x
array([[ 0, 1, 2, 3],
[10, 11, 12, 13],
[20, 21, 22, 23]])
>>> shape = (2,2)
>>> v = sliding_window_view(x, shape)
>>> v.shape
(2, 3, 2, 2)
>>> v
array([[[[ 0, 1],
[10, 11]],
[[ 1, 2],
[11, 12]],
[[ 2, 3],
[12, 13]]],
[[[10, 11],
[20, 21]],
[[11, 12],
[21, 22]],
[[12, 13],
[22, 23]]]])
The axis can be specified explicitly:
>>> v = sliding_window_view(x, 3, 0)
>>> v.shape
(1, 4, 3)
>>> v
array([[[ 0, 10, 20],
[ 1, 11, 21],
[ 2, 12, 22],
[ 3, 13, 23]]])
The same axis can be used several times. In that case, every use reduces
the corresponding original dimension:
>>> v = sliding_window_view(x, (2, 3), (1, 1))
>>> v.shape
(3, 1, 2, 3)
>>> v
array([[[[ 0, 1, 2],
[ 1, 2, 3]]],
[[[10, 11, 12],
[11, 12, 13]]],
[[[20, 21, 22],
[21, 22, 23]]]])
Combining with stepped slicing (`::step`), this can be used to take sliding
views which skip elements:
>>> x = np.arange(7)
>>> sliding_window_view(x, 5)[:, ::2]
array([[0, 2, 4],
[1, 3, 5],
[2, 4, 6]])
or views which move by multiple elements
>>> x = np.arange(7)
>>> sliding_window_view(x, 3)[::2, :]
array([[0, 1, 2],
[2, 3, 4],
[4, 5, 6]])
A common application of `sliding_window_view` is the calculation of running
statistics. The simplest example is the
`moving average <https://en.wikipedia.org/wiki/Moving_average>`_:
>>> x = np.arange(6)
>>> x.shape
(6,)
>>> v = sliding_window_view(x, 3)
>>> v.shape
(4, 3)
>>> v
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5]])
>>> moving_average = v.mean(axis=-1)
>>> moving_average
array([1., 2., 3., 4.])
"""
Note that a sliding window approach is often **not** optimal (see Notes).
"""
# 将窗口形状转换为元组,如果window_shape是可迭代对象的话;否则转换为单元素元组
window_shape = (tuple(window_shape)
if np.iterable(window_shape)
else (window_shape,))
# 将输入数组转换为numpy数组,保留可能存在的子类
x = np.array(x, copy=None, subok=subok)
# 将窗口形状转换为numpy数组
window_shape_array = np.array(window_shape)
# 检查窗口形状数组中是否有负值,若有则引发ValueError异常
if np.any(window_shape_array < 0):
raise ValueError('`window_shape` cannot contain negative values')
# 如果axis为None,则默认使用所有维度的轴
if axis is None:
axis = tuple(range(x.ndim))
# 检查window_shape与x的维度数是否一致,若不一致则引发ValueError异常
if len(window_shape) != len(axis):
raise ValueError(f'Since axis is `None`, must provide '
f'window_shape for all dimensions of `x`; '
f'got {len(window_shape)} window_shape elements '
f'and `x.ndim` is {x.ndim}.')
else:
# 标准化axis,确保所有轴都在有效范围内
axis = normalize_axis_tuple(axis, x.ndim, allow_duplicate=True)
# 检查window_shape与axis的长度是否一致,若不一致则引发ValueError异常
if len(window_shape) != len(axis):
raise ValueError(f'Must provide matching length window_shape and '
f'axis; got {len(window_shape)} window_shape '
f'elements and {len(axis)} axes elements.')
# 计算输出数组的步幅
out_strides = x.strides + tuple(x.strides[ax] for ax in axis)
# 调整输入数组的形状,以确保每个轴上窗口的合法性
x_shape_trimmed = list(x.shape)
for ax, dim in zip(axis, window_shape):
if x_shape_trimmed[ax] < dim:
raise ValueError(
'window shape cannot be larger than input array shape')
x_shape_trimmed[ax] -= dim - 1
out_shape = tuple(x_shape_trimmed) + window_shape
# 返回按需切片的数组,以形成窗口视图
return as_strided(x, strides=out_strides, shape=out_shape,
subok=subok, writeable=writeable)
# 将形状参数转换为元组,如果形状是可迭代的,则转换为元组,否则创建只包含一个元素的元组
shape = tuple(shape) if np.iterable(shape) else (shape,)
# 使用给定的参数创建一个新的 NumPy 数组,将 array 转换为数组,不复制数据,允许子类化
array = np.array(array, copy=None, subok=subok)
# 如果形状为空且 array 的形状不为空,则抛出值错误异常,说明无法将非标量广播到标量数组
if not shape and array.shape:
raise ValueError('cannot broadcast a non-scalar to a scalar array')
# 如果形状中有任何负数元素,则抛出值错误异常,说明广播形状的所有元素必须是非负的
if any(size < 0 for size in shape):
raise ValueError('all elements of broadcast shape must be non-negative')
# 定义额外参数列表为空列表
extras = []
# 使用 np.nditer 迭代器创建一个迭代器对象 it,以便按照形状 shape 广播 array
it = np.nditer(
(array,), flags=['multi_index', 'refs_ok', 'zerosize_ok'] + extras,
op_flags=['readonly'], itershape=shape, order='C')
# 进入迭代器上下文
with it:
# 从迭代器获取广播后的视图,即 itviews 列表的第一个元素
broadcast = it.itviews[0]
# 调用 _maybe_view_as_subclass 函数,返回 array 或 broadcast 的可能子类视图
result = _maybe_view_as_subclass(array, broadcast)
# 如果 readonly 为 False 且 array 具有 _writeable_no_warn 标志,则设置 result 的写标志和写警告标志
# 这部分代码将来会被移除
if not readonly and array.flags._writeable_no_warn:
result.flags.writeable = True
result.flags._warn_on_write = True
# 返回广播后的结果数组 result
return result
# 从索引 32 开始,每隔 31 个元素取一个位置进行迭代
for pos in range(32, len(args), 31):
# 使用广播(broadcasting)来避免分配完整的数组
# 具讽刺意味的是,np.broadcast 不能正确处理 np.broadcast 对象(它将它们视为标量)
b = broadcast_to(0, b.shape)
# 将广播应用于参数数组的子集(从 pos 到 pos+31),包括 b 本身
b = np.broadcast(b, *args[pos:(pos + 31)])
# 返回广播后的数组的形状
return b.shape
# 定义一个空的 NumPy 数据类型作为默认值
_size0_dtype = np.dtype([])
@set_module('numpy')
# 将输入的形状广播成单个形状。
def broadcast_shapes(*args):
"""
Broadcast the input shapes into a single shape.
:ref:`Learn more about broadcasting here <basics.broadcasting>`.
.. versionadded:: 1.20.0
Parameters
----------
*args : tuples of ints, or ints
The shapes to be broadcast against each other.
Returns
-------
tuple
Broadcasted shape.
Raises
------
ValueError
If the shapes are not compatible and cannot be broadcast according
to NumPy's broadcasting rules.
See Also
--------
broadcast
broadcast_arrays
broadcast_to
Examples
--------
>>> np.broadcast_shapes((1, 2), (3, 1), (3, 2))
(3, 2)
>>> np.broadcast_shapes((6, 7), (5, 6, 1), (7,), (5, 1, 7))
(5, 6, 7)
"""
# 创建一个包含指定形状的空数组列表,使用默认的空数据类型 _size0_dtype
arrays = [np.empty(x, dtype=_size0_dtype) for x in args]
# 调用内部函数 _broadcast_shape 对数组进行广播操作,并返回结果
return _broadcast_shape(*arrays)
# 定义 _broadcast_arrays_dispatcher 函数,用于分发 broadcast_arrays 函数的参数
def _broadcast_arrays_dispatcher(*args, subok=None):
return args
@array_function_dispatch(_broadcast_arrays_dispatcher, module='numpy')
# 广播任意数量的数组。
def broadcast_arrays(*args, subok=False):
"""
Broadcast any number of arrays against each other.
Parameters
----------
*args : array_likes
The arrays to broadcast.
subok : bool, optional
If True, then sub-classes will be passed-through, otherwise
the returned arrays will be forced to be a base-class array (default).
Returns
-------
broadcasted : tuple of arrays
These arrays are views on the original arrays. They are typically
not contiguous. Furthermore, more than one element of a
broadcasted array may refer to a single memory location. If you need
to write to the arrays, make copies first. While you can set the
``writable`` flag True, writing to a single output value may end up
changing more than one location in the output array.
.. deprecated:: 1.17
The output is currently marked so that if written to, a deprecation
warning will be emitted. A future version will set the
``writable`` flag False so writing to it will raise an error.
See Also
--------
broadcast
broadcast_to
broadcast_shapes
Examples
--------
>>> x = np.array([[1,2,3]])
>>> y = np.array([[4],[5]])
>>> np.broadcast_arrays(x, y)
(array([[1, 2, 3],
[1, 2, 3]]),
array([[4, 4, 4],
[5, 5, 5]]))
Here is a useful idiom for getting contiguous copies instead of
non-contiguous views.
>>> [np.array(a) for a in np.broadcast_arrays(x, y)]
[array([[1, 2, 3],
[1, 2, 3]]),
array([[4, 4, 4],
[5, 5, 5]])]
"""
# nditer is not used here to avoid the limit of 32 arrays.
# Otherwise, something like the following one-liner would suffice:
# return np.nditer(args, flags=['multi_index', 'zerosize_ok'],
# order='C').itviews
# 列表推导式,对传入的每个参数进行处理,将其转换为 NumPy 数组
args = [np.array(_m, copy=None, subok=subok) for _m in args]
# 计算广播后的数组形状,_broadcast_shape 是一个自定义函数用于计算广播形状
shape = _broadcast_shape(*args)
# 列表推导式,对每个数组进行检查和处理:
# 如果数组形状与广播后的形状相同,则保持不变
# 否则,使用 _broadcast_to 函数将数组广播到指定形状
result = [array if array.shape == shape
else _broadcast_to(array, shape, subok=subok, readonly=False)
for array in args]
# 返回结果元组,其中包含广播后的所有数组
return tuple(result)
.\numpy\numpy\lib\_stride_tricks_impl.pyi
from collections.abc import Iterable
from typing import Any, TypeVar, overload, SupportsIndex
from numpy import generic
from numpy._typing import (
NDArray,
ArrayLike,
_ShapeLike,
_Shape,
_ArrayLike
)
_SCT = TypeVar("_SCT", bound=generic)
__all__: list[str]
class DummyArray:
__array_interface__: dict[str, Any]
base: None | NDArray[Any]
def __init__(
self,
interface: dict[str, Any],
base: None | NDArray[Any] = ...,
) -> None:
...
@overload
def as_strided(
x: _ArrayLike[_SCT],
shape: None | Iterable[int] = ...,
strides: None | Iterable[int] = ...,
subok: bool = ...,
writeable: bool = ...,
) -> NDArray[_SCT]: ...
@overload
def as_strided(
x: ArrayLike,
shape: None | Iterable[int] = ...,
strides: None | Iterable[int] = ...,
subok: bool = ...,
writeable: bool = ...,
) -> NDArray[Any]: ...
@overload
def sliding_window_view(
x: _ArrayLike[_SCT],
window_shape: int | Iterable[int],
axis: None | SupportsIndex = ...,
*,
subok: bool = ...,
writeable: bool = ...,
) -> NDArray[_SCT]: ...
@overload
def sliding_window_view(
x: ArrayLike,
window_shape: int | Iterable[int],
axis: None | SupportsIndex = ...,
*,
subok: bool = ...,
writeable: bool = ...,
) -> NDArray[Any]: ...
@overload
def broadcast_to(
array: _ArrayLike[_SCT],
shape: int | Iterable[int],
subok: bool = ...,
) -> NDArray[_SCT]: ...
@overload
def broadcast_to(
array: ArrayLike,
shape: int | Iterable[int],
subok: bool = ...,
) -> NDArray[Any]: ...
def broadcast_shapes(*args: _ShapeLike) -> _Shape:
...
def broadcast_arrays(
*args: ArrayLike,
subok: bool = ...,
) -> tuple[NDArray[Any], ...]:
...
.\numpy\numpy\lib\_twodim_base_impl.py
""" Basic functions for manipulating 2d arrays
"""
import functools
import operator
from numpy._core._multiarray_umath import _array_converter
from numpy._core.numeric import (
asanyarray, arange, zeros, greater_equal, multiply, ones,
asarray, where, int8, int16, int32, int64, intp, empty, promote_types,
diagonal, nonzero, indices
)
from numpy._core.overrides import set_array_function_like_doc, set_module
from numpy._core import overrides
from numpy._core import iinfo
from numpy.lib._stride_tricks_impl import broadcast_to
__all__ = [
'diag', 'diagflat', 'eye', 'fliplr', 'flipud', 'tri', 'triu',
'tril', 'vander', 'histogram2d', 'mask_indices', 'tril_indices',
'tril_indices_from', 'triu_indices', 'triu_indices_from', ]
array_function_dispatch = functools.partial(
overrides.array_function_dispatch, module='numpy')
i1 = iinfo(int8)
i2 = iinfo(int16)
i4 = iinfo(int32)
def _min_int(low, high):
""" get small int that fits the range """
if high <= i1.max and low >= i1.min:
return int8
if high <= i2.max and low >= i2.min:
return int16
if high <= i4.max and low >= i4.min:
return int32
return int64
def _flip_dispatcher(m):
return (m,)
@array_function_dispatch(_flip_dispatcher)
def fliplr(m):
"""
Reverse the order of elements along axis 1 (left/right).
For a 2-D array, this flips the entries in each row in the left/right
direction. Columns are preserved, but appear in a different order than
before.
Parameters
----------
m : array_like
Input array, must be at least 2-D.
Returns
-------
f : ndarray
A view of `m` with the columns reversed. Since a view
is returned, this operation is :math:`\\mathcal O(1)`.
See Also
--------
flipud : Flip array in the up/down direction.
flip : Flip array in one or more dimensions.
rot90 : Rotate array counterclockwise.
Notes
-----
Equivalent to ``m[:,::-1]`` or ``np.flip(m, axis=1)``.
Requires the array to be at least 2-D.
Examples
--------
>>> A = np.diag([1.,2.,3.])
>>> A
array([[1., 0., 0.],
[0., 2., 0.],
[0., 0., 3.]])
>>> np.fliplr(A)
array([[0., 0., 1.],
[0., 2., 0.],
[3., 0., 0.]])
>>> rng = np.random.default_rng()
>>> A = rng.normal(size=(2,3,5))
>>> np.all(np.fliplr(A) == A[:,::-1,...])
True
"""
m = asanyarray(m)
if m.ndim < 2:
raise ValueError("Input must be >= 2-d.")
return m[:, ::-1]
@array_function_dispatch(_flip_dispatcher)
def flipud(m):
"""
Reverse the order of elements along axis 0 (up/down).
For a 2-D array, this flips the entries in each column in the up/down
direction. Rows are preserved, but appear in a different order than before.
Parameters
----------
m : array_like
Input array.
Returns
-------
# 将输入的数组 m 转换为 numpy 数组,确保能够进行后续操作
m = asanyarray(m)
# 如果输入数组的维度小于 1,则抛出值错误异常
if m.ndim < 1:
raise ValueError("Input must be >= 1-d.")
# 返回翻转行的视图数组,相当于 m[::-1, ...] 的操作
return m[::-1, ...]
# 用于设置函数的数组功能文档样式
@set_array_function_like_doc
# 用于设置函数的模块为 'numpy'
@set_module('numpy')
# 定义一个名为 eye 的函数,生成一个二维数组,对角线为 1,其他位置为 0
def eye(N, M=None, k=0, dtype=float, order='C', *, device=None, like=None):
"""
Return a 2-D array with ones on the diagonal and zeros elsewhere.
Parameters
----------
N : int
Number of rows in the output.
M : int, optional
Number of columns in the output. If None, defaults to `N`.
k : int, optional
Index of the diagonal: 0 (the default) refers to the main diagonal,
a positive value refers to an upper diagonal, and a negative value
to a lower diagonal.
dtype : data-type, optional
Data-type of the returned array.
order : {'C', 'F'}, optional
Whether the output should be stored in row-major (C-style) or
column-major (Fortran-style) order in memory.
.. versionadded:: 1.14.0
device : str, optional
The device on which to place the created array. Default: None.
For Array-API interoperability only, so must be ``"cpu"`` if passed.
.. versionadded:: 2.0.0
${ARRAY_FUNCTION_LIKE}
.. versionadded:: 1.20.0
Returns
-------
I : ndarray of shape (N,M)
An array where all elements are equal to zero, except for the `k`-th
diagonal, whose values are equal to one.
See Also
--------
identity : (almost) equivalent function
diag : diagonal 2-D array from a 1-D array specified by the user.
Examples
--------
>>> np.eye(2, dtype=int)
array([[1, 0],
[0, 1]])
>>> np.eye(3, k=1)
array([[0., 1., 0.],
[0., 0., 1.],
[0., 0., 0.]])
"""
# 如果 like 参数不为 None,则调用 _eye_with_like 函数处理
if like is not None:
return _eye_with_like(
like, N, M=M, k=k, dtype=dtype, order=order, device=device
)
# 如果 M 为 None,则将 M 设为 N
if M is None:
M = N
# 创建一个形状为 (N, M) 的零数组 m,数据类型为 dtype,存储顺序为 order,设备为 device
m = zeros((N, M), dtype=dtype, order=order, device=device)
# 如果 k 大于等于 M,则直接返回 m
if k >= M:
return m
# 确保 M 和 k 是整数,以避免意外的类型转换结果
M = operator.index(M)
k = operator.index(k)
# 如果 k 大于等于 0,则将 i 设为 k;否则将 i 设为 (-k) * M
if k >= 0:
i = k
else:
i = (-k) * M
# 在 m 的前 M-k 行中,每隔 M+1 个元素设置为 1,从索引 i 开始
m[:M-k].flat[i::M+1] = 1
# 返回生成的二维数组 m
return m
# 通过数组函数分发装饰器将 _eye_with_like 函数与 eye 函数关联起来
_eye_with_like = array_function_dispatch()(eye)
# 定义一个 _diag_dispatcher 函数,用于 diag 函数的分派
def _diag_dispatcher(v, k=None):
return (v,)
# 通过数组函数分发装饰器将 _diag_dispatcher 函数与 diag 函数关联起来
@array_function_dispatch(_diag_dispatcher)
# 定义 diag 函数,用于提取对角线或构造对角线数组
def diag(v, k=0):
"""
Extract a diagonal or construct a diagonal array.
See the more detailed documentation for ``numpy.diagonal`` if you use this
function to extract a diagonal and wish to write to the resulting array;
whether it returns a copy or a view depends on what version of numpy you
are using.
Parameters
----------
v : array_like
If `v` is a 2-D array, return a copy of its `k`-th diagonal.
If `v` is a 1-D array, return a 2-D array with `v` on the `k`-th
diagonal.
"""
v = asanyarray(v)
s = v.shape
# 将输入转换为任意数组,确保可以处理不同类型的输入
if len(s) == 1:
# 如果输入是一维数组
n = s[0]+abs(k)
# 计算输出数组的大小,包括需要的额外对角线长度
res = zeros((n, n), v.dtype)
# 创建一个全零数组作为输出,与输入数组类型相同
if k >= 0:
i = k
else:
i = (-k) * n
# 计算对角线的起始索引
res[:n-k].flat[i::n+1] = v
# 将输入数组的值填充到输出数组的对角线上
return res
elif len(s) == 2:
# 如果输入是二维数组
return diagonal(v, k)
# 调用 diagonal 函数返回指定位置的对角线数组
else:
# 处理不支持的输入维度
raise ValueError("Input must be 1- or 2-d.")
# 抛出值错误,要求输入必须是一维或二维数组
@array_function_dispatch(_diag_dispatcher)
# 使用装饰器将 _diag_dispatcher 函数与 diagflat 函数关联,用于数组函数分发
def diagflat(v, k=0):
"""
Create a two-dimensional array with the flattened input as a diagonal.
Parameters
----------
v : array_like
Input data, which is flattened and set as the `k`-th
diagonal of the output.
k : int, optional
Diagonal to set; 0, the default, corresponds to the "main" diagonal,
a positive (negative) `k` giving the number of the diagonal above
(below) the main.
Returns
-------
out : ndarray
The 2-D output array.
See Also
--------
diag : MATLAB work-alike for 1-D and 2-D arrays.
diagonal : Return specified diagonals.
trace : Sum along diagonals.
Examples
--------
>>> np.diagflat([[1,2], [3,4]])
array([[1, 0, 0, 0],
[0, 2, 0, 0],
[0, 0, 3, 0],
[0, 0, 0, 4]])
>>> np.diagflat([1,2], 1)
array([[0, 1, 0],
[0, 0, 2],
[0, 0, 0]])
"""
# 转换输入数据 v 并展平
conv = _array_converter(v)
v, = conv.as_arrays(subok=False)
v = v.ravel()
s = len(v)
n = s + abs(k)
# 创建一个形状为 (n, n) 的零数组,指定数据类型为 v 的数据类型
res = zeros((n, n), v.dtype)
if (k >= 0):
# 对于 k >= 0 的情况,设置正对角线及其上的对角线
i = arange(0, n-k, dtype=intp)
fi = i+k+i*n
else:
# 对于 k < 0 的情况,设置负对角线及其下的对角线
i = arange(0, n+k, dtype=intp)
fi = i+(i-k)*n
# 将展平的 v 数组数据设置到 res 的指定位置
res.flat[fi] = v
return conv.wrap(res)
@set_array_function_like_doc
@set_module('numpy')
# 使用装饰器设置 tri 函数的数组函数行为及所属模块为 numpy
def tri(N, M=None, k=0, dtype=float, *, like=None):
"""
An array with ones at and below the given diagonal and zeros elsewhere.
Parameters
----------
N : int
Number of rows in the array.
M : int, optional
Number of columns in the array.
By default, `M` is taken equal to `N`.
k : int, optional
The sub-diagonal at and below which the array is filled.
`k` = 0 is the main diagonal, while `k` < 0 is below it,
and `k` > 0 is above. The default is 0.
dtype : dtype, optional
Data type of the returned array. The default is float.
${ARRAY_FUNCTION_LIKE}
.. versionadded:: 1.20.0
Returns
-------
tri : ndarray of shape (N, M)
Array with its lower triangle filled with ones and zero elsewhere;
in other words ``T[i,j] == 1`` for ``j <= i + k``, 0 otherwise.
Examples
--------
>>> np.tri(3, 5, 2, dtype=int)
array([[1, 1, 1, 0, 0],
[1, 1, 1, 1, 0],
[1, 1, 1, 1, 1]])
>>> np.tri(3, 5, -1)
array([[0., 0., 0., 0., 0.],
[1., 0., 0., 0., 0.],
[1., 1., 0., 0., 0.]])
"""
if like is not None:
# 如果指定了 like 参数,返回与 like 相同类型的三角矩阵
return _tri_with_like(like, N, M=M, k=k, dtype=dtype)
if M is None:
M = N
# 创建一个布尔类型的 N x M 形状的矩阵,其中下三角(包括对角线)为 1,其余为 0
m = greater_equal.outer(arange(N, dtype=_min_int(0, N)),
arange(-k, M-k, dtype=_min_int(-k, M - k)))
# 避免在已经是布尔类型时复制矩阵
m = m.astype(dtype, copy=False)
return m
# 将 array_function_dispatch 装饰器应用到 tri 函数
_tri_with_like = array_function_dispatch()(tri)
# 根据输入参数生成一个 Vandermonde 矩阵
def vander(x, N=None, increasing=False):
# 如果 N 为 None,则设置 N 为 x 的长度
if N is None:
N = len(x)
# 根据 increasing 参数决定是否递增排序
if increasing:
# 生成递增排序的 Vandermonde 矩阵
return array([x**(N-1-i) for i in range(N)]).T
else:
# 生成递减排序的 Vandermonde 矩阵
return array([x**i for i in range(N)]).T
"""
The columns of the output matrix are powers of the input vector. The
order of the powers is determined by the `increasing` boolean argument.
Specifically, when `increasing` is False, the `i`-th output column is
the input vector raised element-wise to the power of ``N - i - 1``. Such
a matrix with a geometric progression in each row is named for Alexandre-
Theophile Vandermonde.
Parameters
----------
x : array_like
1-D input array.
N : int, optional
Number of columns in the output. If `N` is not specified, a square
array is returned (``N = len(x)``).
increasing : bool, optional
Order of the powers of the columns. If True, the powers increase
from left to right, if False (the default) they are reversed.
.. versionadded:: 1.9.0
Returns
-------
out : ndarray
Vandermonde matrix. If `increasing` is False, the first column is
``x^(N-1)``, the second ``x^(N-2)`` and so forth. If `increasing` is
True, the columns are ``x^0, x^1, ..., x^(N-1)``.
See Also
--------
polynomial.polynomial.polyvander
Examples
--------
>>> x = np.array([1, 2, 3, 5])
>>> N = 3
>>> np.vander(x, N)
array([[ 1, 1, 1],
[ 4, 2, 1],
[ 9, 3, 1],
[25, 5, 1]])
>>> np.column_stack([x**(N-1-i) for i in range(N)])
array([[ 1, 1, 1],
[ 4, 2, 1],
[ 9, 3, 1],
[25, 5, 1]])
>>> x = np.array([1, 2, 3, 5])
>>> np.vander(x)
array([[ 1, 1, 1, 1],
[ 8, 4, 2, 1],
[ 27, 9, 3, 1],
[125, 25, 5, 1]])
>>> np.vander(x, increasing=True)
array([[ 1, 1, 1, 1],
[ 1, 2, 4, 8],
[ 1, 3, 9, 27],
[ 1, 5, 25, 125]])
The determinant of a square Vandermonde matrix is the product
of the differences between the values of the input vector:
>>> np.linalg.det(np.vander(x))
48.000000000000043
>>> (5-3)*(5-2)*(5-1)*(3-2)*(3-1)*(2-1)
48
"""
# 将输入数组 x 转换为 ndarray 类型
x = asarray(x)
# 如果 x 不是一维数组,则抛出异常
if x.ndim != 1:
raise ValueError("x must be a one-dimensional array or sequence.")
# 如果未指定 N,则将 N 设置为 x 的长度
if N is None:
N = len(x)
# 创建一个空的数组 v,形状为 (len(x), N),数据类型为 x 的数据类型和整数类型的广播类型
v = empty((len(x), N), dtype=promote_types(x.dtype, int))
# 根据 increasing 参数选择操作数组 tmp
tmp = v[:, ::-1] if not increasing else v
# 如果 N > 0,则将 tmp 的第一列设置为 1
if N > 0:
tmp[:, 0] = 1
# 如果 N > 1,则将 tmp 的第二列到最后一列设置为 x 的列向量的累积乘积
if N > 1:
tmp[:, 1:] = x[:, None]
multiply.accumulate(tmp[:, 1:], out=tmp[:, 1:], axis=1)
# 返回生成的 Vandermonde 矩阵 v
return v
def _histogram2d_dispatcher(x, y, bins=None, range=None, density=None,
weights=None):
# 生成器函数,用于分派参数 x, y, bins, range, density, weights
yield x # 生成器返回 x
yield y # 生成器返回 y
# 以下逻辑从 histogram2d 中的检查逻辑进行了糟糕的适应
try:
N = len(bins) # 尝试获取 bins 的长度
except TypeError:
N = 1 # 如果无法获取长度,则默认 N 为 1
if N == 2:
yield from bins # 如果 N 等于 2,则返回 bins 中的元素 [x, y]
else:
yield bins # 否则返回 bins
yield weights # 返回 weights
@array_function_dispatch(_histogram2d_dispatcher)
def histogram2d(x, y, bins=10, range=None, density=None, weights=None):
"""
Compute the bi-dimensional histogram of two data samples.
Parameters
----------
x : array_like, shape (N,)
An array containing the x coordinates of the points to be
histogrammed.
y : array_like, shape (N,)
An array containing the y coordinates of the points to be
histogrammed.
bins : int or array_like or [int, int] or [array, array], optional
The bin specification:
* If int, the number of bins for the two dimensions (nx=ny=bins).
* If array_like, the bin edges for the two dimensions
(x_edges=y_edges=bins).
* If [int, int], the number of bins in each dimension
(nx, ny = bins).
* If [array, array], the bin edges in each dimension
(x_edges, y_edges = bins).
* A combination [int, array] or [array, int], where int
is the number of bins and array is the bin edges.
range : array_like, shape(2,2), optional
The leftmost and rightmost edges of the bins along each dimension
(if not specified explicitly in the `bins` parameters):
``[[xmin, xmax], [ymin, ymax]]``. All values outside of this range
will be considered outliers and not tallied in the histogram.
density : bool, optional
If False, the default, returns the number of samples in each bin.
If True, returns the probability *density* function at the bin,
``bin_count / sample_count / bin_area``.
weights : array_like, shape(N,), optional
An array of values ``w_i`` weighing each sample ``(x_i, y_i)``.
Weights are normalized to 1 if `density` is True. If `density` is
False, the values of the returned histogram are equal to the sum of
the weights belonging to the samples falling into each bin.
Returns
-------
H : ndarray, shape(nx, ny)
The bi-dimensional histogram of samples `x` and `y`. Values in `x`
are histogrammed along the first dimension and values in `y` are
histogrammed along the second dimension.
xedges : ndarray, shape(nx+1,)
The bin edges along the first dimension.
yedges : ndarray, shape(ny+1,)
The bin edges along the second dimension.
See Also
--------
histogram : 1D histogram
histogramdd : Multidimensional histogram
Notes
-----
When `density` is True, then the returned histogram is the sample
density, defined such that the sum over bins of the product
"""
pass # 空函数体,因为函数文档字符串已经提供了函数功能的说明
# `bin_value * bin_area` is 1.
# 上述表达式中 `bin_value * bin_area` 的结果为1。
# Please note that the histogram does not follow the Cartesian convention
# where `x` values are on the abscissa and `y` values on the ordinate
# axis. Rather, `x` is histogrammed along the first dimension of the
# array (vertical), and `y` along the second dimension of the array
# (horizontal). This ensures compatibility with `histogramdd`.
# 请注意,直方图不遵循笛卡尔坐标系的传统规定,其中 `x` 值位于横坐标轴上,
# `y` 值位于纵坐标轴上。相反,`x` 被直方图化沿着数组的第一个维度(垂直方向),
# `y` 被直方图化沿着数组的第二个维度(水平方向)。这样做确保与 `histogramdd` 兼容。
# Examples
# --------
# 例子
# Import necessary modules
# 导入必要的模块
>>> from matplotlib.image import NonUniformImage
>>> import matplotlib.pyplot as plt
# Construct a 2-D histogram with variable bin width. First define the bin
# edges:
# 构建一个具有可变箱宽的二维直方图。首先定义箱子的边缘:
>>> xedges = [0, 1, 3, 5]
>>> yedges = [0, 2, 3, 4, 6]
# Next we create a histogram H with random bin content:
# 接下来,我们用随机箱内容创建直方图 H:
>>> x = np.random.normal(2, 1, 100)
>>> y = np.random.normal(1, 1, 100)
>>> H, xedges, yedges = np.histogram2d(x, y, bins=(xedges, yedges))
# Histogram does not follow Cartesian convention (see Notes),
# therefore transpose H for visualization purposes.
# 直方图不遵循笛卡尔坐标系的传统规定(见注释),因此为了可视化目的转置 H。
>>> H = H.T
# :func:`imshow <matplotlib.pyplot.imshow>` can only display square bins:
# :func:`imshow <matplotlib.pyplot.imshow>` 只能显示正方形的箱子:
>>> fig = plt.figure(figsize=(7, 3))
>>> ax = fig.add_subplot(131, title='imshow: square bins')
>>> plt.imshow(H, interpolation='nearest', origin='lower',
... extent=[xedges[0], xedges[-1], yedges[0], yedges[-1]])
# :func:`pcolormesh <matplotlib.pyplot.pcolormesh>` can display actual edges:
# :func:`pcolormesh <matplotlib.pyplot.pcolormesh>` 可以显示实际的边缘:
>>> ax = fig.add_subplot(132, title='pcolormesh: actual edges',
... aspect='equal')
>>> X, Y = np.meshgrid(xedges, yedges)
>>> ax.pcolormesh(X, Y, H)
# :class:`NonUniformImage <matplotlib.image.NonUniformImage>` can be used to
# display actual bin edges with interpolation:
# :class:`NonUniformImage <matplotlib.image.NonUniformImage>` 可以用来显示带插值的实际箱边缘:
>>> ax = fig.add_subplot(133, title='NonUniformImage: interpolated',
... aspect='equal', xlim=xedges[[0, -1]], ylim=yedges[[0, -1]])
>>> im = NonUniformImage(ax, interpolation='bilinear')
>>> xcenters = (xedges[:-1] + xedges[1:]) / 2
>>> ycenters = (yedges[:-1] + yedges[1:]) / 2
>>> im.set_data(xcenters, ycenters, H)
>>> ax.add_image(im)
# Show the plot
# 显示图形
>>> plt.show()
# It is also possible to construct a 2-D histogram without specifying bin
# edges:
# 也可以构建一个没有指定箱边界的二维直方图:
>>> # Generate non-symmetric test data
>>> n = 10000
>>> x = np.linspace(1, 100, n)
>>> y = 2*np.log(x) + np.random.rand(n) - 0.5
>>> # Compute 2d histogram. Note the order of x/y and xedges/yedges
>>> H, yedges, xedges = np.histogram2d(y, x, bins=20)
# Now we can plot the histogram using
# :func:`pcolormesh <matplotlib.pyplot.pcolormesh>`, and a
# :func:`hexbin <matplotlib.pyplot.hexbin>` for comparison.
# 现在我们可以使用 :func:`pcolormesh <matplotlib.pyplot.pcolormesh>` 绘制直方图,
# 并使用 :func:`hexbin <matplotlib.pyplot.hexbin>` 进行比较。
>>> # Plot histogram using pcolormesh
>>> fig, (ax1, ax2) = plt.subplots(ncols=2, sharey=True)
>>> ax1.pcolormesh(xedges, yedges, H, cmap='rainbow')
>>> ax1.plot(x, 2*np.log(x), 'k-')
>>> ax1.set_xlim(x.min(), x.max())
>>> ax1.set_ylim(y.min(), y.max())
>>> ax1.set_xlabel('x')
>>> ax1.set_ylabel('y')
>>> ax1.set_title('histogram2d')
>>> ax1.grid()
>>> # 在 ax1 上创建二维直方图
>>> # 设置 y 轴的范围为 y 的最小值到最大值
>>> ax1.set_ylim(y.min(), y.max())
>>> # 设置 x 轴标签为 'x'
>>> ax1.set_xlabel('x')
>>> # 设置 y 轴标签为 'y'
>>> ax1.set_ylabel('y')
>>> # 设置图表标题为 'histogram2d'
>>> ax1.set_title('histogram2d')
>>> # 在 ax1 上显示网格线
>>> ax1.grid()
>>> # 在 ax2 上创建 hexbin 图进行比较
>>> ax2.hexbin(x, y, gridsize=20, cmap='rainbow')
>>> # 绘制直线图,x 为自变量,2*np.log(x) 为因变量,线条为黑色实线
>>> ax2.plot(x, 2*np.log(x), 'k-')
>>> # 设置 ax2 的标题为 'hexbin'
>>> ax2.set_title('hexbin')
>>> # 设置 x 轴的范围为 x 的最小值到最大值
>>> ax2.set_xlim(x.min(), x.max())
>>> # 设置 x 轴标签为 'x'
>>> ax2.set_xlabel('x')
>>> # 在 ax2 上显示网格线
>>> ax2.grid()
>>> # 显示整个图形
>>> plt.show()
"""
from numpy import histogramdd
if len(x) != len(y):
raise ValueError('x and y must have the same length.')
try:
N = len(bins)
except TypeError:
N = 1
if N != 1 and N != 2:
xedges = yedges = asarray(bins)
bins = [xedges, yedges]
hist, edges = histogramdd([x, y], bins, range, density, weights)
return hist, edges[0], edges[1]
@set_module('numpy')
def mask_indices(n, mask_func, k=0):
"""
Return the indices to access (n, n) arrays, given a masking function.
Assume `mask_func` is a function that, for a square array a of size
``(n, n)`` with a possible offset argument `k`, when called as
``mask_func(a, k)`` returns a new array with zeros in certain locations
(functions like `triu` or `tril` do precisely this). Then this function
returns the indices where the non-zero values would be located.
Parameters
----------
n : int
The returned indices will be valid to access arrays of shape (n, n).
mask_func : callable
A function whose call signature is similar to that of `triu`, `tril`.
That is, ``mask_func(x, k)`` returns a boolean array, shaped like `x`.
`k` is an optional argument to the function.
k : scalar
An optional argument which is passed through to `mask_func`. Functions
like `triu`, `tril` take a second argument that is interpreted as an
offset.
Returns
-------
indices : tuple of arrays.
The `n` arrays of indices corresponding to the locations where
``mask_func(np.ones((n, n)), k)`` is True.
See Also
--------
triu, tril, triu_indices, tril_indices
Notes
-----
.. versionadded:: 1.4.0
Examples
--------
These are the indices that would allow you to access the upper triangular
part of any 3x3 array:
>>> iu = np.mask_indices(3, np.triu)
For example, if `a` is a 3x3 array:
>>> a = np.arange(9).reshape(3, 3)
>>> a
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>> a[iu]
array([0, 1, 2, 4, 5, 8])
An offset can be passed also to the masking function. This gets us the
indices starting on the first diagonal right of the main one:
>>> iu1 = np.mask_indices(3, np.triu, 1)
with which we now extract only three elements:
>>> a[iu1]
array([1, 2, 5])
"""
m = ones((n, n), int)
a = mask_func(m, k)
return nonzero(a != 0)
@set_module('numpy')
def tril_indices(n, k=0, m=None):
"""
Return the indices for the lower-triangle of an (n, m) array.
Parameters
----------
n : int
The row dimension of the arrays for which the returned
indices will be valid.
k : int, optional
Diagonal offset (see `tril` for details).
m : int, optional
.. versionadded:: 1.9.0
The column dimension of the arrays for which the returned
arrays will be valid.
By default `m` is taken equal to `n`.
Returns
-------
inds : tuple of arrays
The indices for the triangle. The returned tuple contains two arrays,
each with the indices along one dimension of the array.
See also
--------
triu_indices : similar function, for upper-triangular.
mask_indices : generic function accepting an arbitrary mask function.
tril, triu
Notes
"""
.. versionadded:: 1.4.0
il1 = np.tril_indices(4)
il2 = np.tril_indices(4, 2)
a = np.arange(16).reshape(4, 4)
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
>>> a[il1]
array([ 0, 4, 5, 8, 9, 10, 12, 13, 14, 15])
>>> a[il1] = -1
>>> a
array([[-1, 1, 2, 3],
[-1, -1, 6, 7],
[-1, -1, -1, 11],
[-1, -1, -1, -1]])
>>> a[il2] = -10
>>> a
array([[-10, -10, -10, 3],
[-10, -10, -10, -10],
[-10, -10, -10, -10],
[-10, -10, -10, -10]])
"""
tri_ = tri(n, m, k=k, dtype=bool)
# 返回一个元组,其中每个元素是根据布尔数组 tri_ 的形状广播后的 inds 的值
return tuple(broadcast_to(inds, tri_.shape)[tri_]
for inds in indices(tri_.shape, sparse=True))
# 定义一个函数分派器,返回输入参数的元组
def _trilu_indices_form_dispatcher(arr, k=None):
return (arr,)
# 使用装饰器将下面的函数注册到数组函数分派机制中
@array_function_dispatch(_trilu_indices_form_dispatcher)
# 定义函数 tril_indices_from,返回给定数组的下三角部分的索引
def tril_indices_from(arr, k=0):
"""
返回数组的下三角部分的索引。
查看 `tril_indices` 获取详细信息。
Parameters
----------
arr : array_like
索引适用于维度与 arr 相同的方形数组。
k : int, optional
对角线偏移量(详见 `tril` 的说明)。
Examples
--------
创建一个 4x4 的数组。
>>> a = np.arange(16).reshape(4, 4)
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
将数组传递给函数以获取下三角元素的索引。
>>> trili = np.tril_indices_from(a)
>>> trili
(array([0, 1, 1, 2, 2, 2, 3, 3, 3, 3]), array([0, 0, 1, 0, 1, 2, 0, 1, 2, 3]))
>>> a[trili]
array([ 0, 4, 5, 8, 9, 10, 12, 13, 14, 15])
这是 `tril_indices()` 的语法糖。
>>> np.tril_indices(a.shape[0])
(array([0, 1, 1, 2, 2, 2, 3, 3, 3, 3]), array([0, 0, 1, 0, 1, 2, 0, 1, 2, 3]))
使用 `k` 参数来返回到第 k 条对角线的下三角数组的索引。
>>> trili1 = np.tril_indices_from(a, k=1)
>>> a[trili1]
array([ 0, 1, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15])
See Also
--------
tril_indices, tril, triu_indices_from
Notes
-----
.. versionadded:: 1.4.0
"""
# 如果输入数组不是二维的,抛出 ValueError 异常
if arr.ndim != 2:
raise ValueError("input array must be 2-d")
# 返回调用 tril_indices 函数得到的结果,指定数组的行数和列数以及对角线偏移量
return tril_indices(arr.shape[-2], k=k, m=arr.shape[-1])
# 将下面的函数设置为 numpy 模块的一部分
@set_module('numpy')
# 定义 triu_indices 函数,返回一个 (n, m) 数组的上三角部分的索引
def triu_indices(n, k=0, m=None):
"""
返回一个 (n, m) 数组的上三角部分的索引。
Parameters
----------
n : int
返回的索引适用于数组的大小。
k : int, optional
对角线偏移量(详见 `triu` 的说明)。
m : int, optional
.. versionadded:: 1.9.0
返回的数组的列维度。
默认情况下,`m` 等于 `n`。
Returns
-------
inds : tuple, shape(2) of ndarrays, shape(`n`)
三角形的索引。返回的元组包含两个数组,每个数组沿数组的一个维度包含索引。可用于切片形状为 (`n`, `n`) 的 ndarray。
See also
--------
tril_indices : 类似的函数,用于下三角。
mask_indices : 接受任意掩码函数的通用函数。
triu, tril
Notes
-----
.. versionadded:: 1.4.0
Examples
--------
计算两组不同的索引以访问 4x4 数组,一组从主对角线开始为上三角部分,另一组从右边开始两个对角线更远的地方:
>>> iu1 = np.triu_indices(4)
>>> iu2 = np.triu_indices(4, 2)
"""
# 此处省略函数主体,因为它只包含了文档字符串和一些函数签名,没有实际的代码实现
# 创建一个布尔类型的三角形掩码,表示矩阵中不同的三角形区域
tri_ = ~tri(n, m, k=k - 1, dtype=bool)
# 返回一个元组,包含通过广播和掩码选择的索引的稀疏矩阵中的元素
return tuple(broadcast_to(inds, tri_.shape)[tri_]
for inds in indices(tri_.shape, sparse=True))
# 使用装饰器来分派函数,根据数组的形式调度
@array_function_dispatch(_trilu_indices_form_dispatcher)
# 定义一个函数,返回给定数组的上三角部分的索引
def triu_indices_from(arr, k=0):
"""
Return the indices for the upper-triangle of arr.
See `triu_indices` for full details.
Parameters
----------
arr : ndarray, shape(N, N)
The indices will be valid for square arrays.
输入数组,应为方形数组,返回的索引对其有效。
k : int, optional
Diagonal offset (see `triu` for details).
对角线的偏移量(参见 `triu` 以了解详情)。
Returns
-------
triu_indices_from : tuple, shape(2) of ndarray, shape(N)
Indices for the upper-triangle of `arr`.
返回数组 `arr` 上三角部分的索引。
Examples
--------
Create a 4 by 4 array.
>>> a = np.arange(16).reshape(4, 4)
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
Pass the array to get the indices of the upper triangular elements.
>>> triui = np.triu_indices_from(a)
>>> triui
(array([0, 0, 0, 0, 1, 1, 1, 2, 2, 3]), array([0, 1, 2, 3, 1, 2, 3, 2, 3, 3]))
>>> a[triui]
array([ 0, 1, 2, 3, 5, 6, 7, 10, 11, 15])
This is syntactic sugar for triu_indices().
>>> np.triu_indices(a.shape[0])
(array([0, 0, 0, 0, 1, 1, 1, 2, 2, 3]), array([0, 1, 2, 3, 1, 2, 3, 2, 3, 3]))
Use the `k` parameter to return the indices for the upper triangular array
from the k-th diagonal.
>>> triuim1 = np.triu_indices_from(a, k=1)
>>> a[triuim1]
array([ 1, 2, 3, 6, 7, 11])
See Also
--------
triu_indices, triu, tril_indices_from
Notes
-----
.. versionadded:: 1.4.0
"""
# 如果输入数组的维度不是2,抛出值错误
if arr.ndim != 2:
raise ValueError("input array must be 2-d")
# 返回调用 triu_indices 函数得到的结果,传递给它数组的形状及 k 参数
return triu_indices(arr.shape[-2], k=k, m=arr.shape[-1])
.\numpy\numpy\lib\_twodim_base_impl.pyi
import builtins
from collections.abc import Callable, Sequence
from typing import (
Any,
overload,
TypeVar,
Literal as L,
)
import numpy as np
from numpy import (
generic,
number,
timedelta64,
datetime64,
int_,
intp,
float64,
signedinteger,
floating,
complexfloating,
object_,
_OrderCF,
)
from numpy._typing import (
DTypeLike,
_DTypeLike,
ArrayLike,
_ArrayLike,
NDArray,
_SupportsArrayFunc,
_ArrayLikeInt_co,
_ArrayLikeFloat_co,
_ArrayLikeComplex_co,
_ArrayLikeObject_co,
)
_T = TypeVar("_T")
_SCT = TypeVar("_SCT", bound=generic)
_MaskFunc = Callable[
[NDArray[int_], _T],
NDArray[number[Any] | np.bool | timedelta64 | datetime64 | object_],
]
__all__: list[str]
@overload
def fliplr(m: _ArrayLike[_SCT]) -> NDArray[_SCT]: ...
@overload
def fliplr(m: ArrayLike) -> NDArray[Any]: ...
@overload
def flipud(m: _ArrayLike[_SCT]) -> NDArray[_SCT]: ...
@overload
def flipud(m: ArrayLike) -> NDArray[Any]: ...
@overload
def eye(
N: int,
M: None | int = ...,
k: int = ...,
dtype: None = ...,
order: _OrderCF = ...,
*,
device: None | L["cpu"] = ...,
like: None | _SupportsArrayFunc = ...,
) -> NDArray[float64]: ...
@overload
def eye(
N: int,
M: None | int = ...,
k: int = ...,
dtype: _DTypeLike[_SCT] = ...,
order: _OrderCF = ...,
*,
device: None | L["cpu"] = ...,
like: None | _SupportsArrayFunc = ...,
) -> NDArray[_SCT]: ...
@overload
def eye(
N: int,
M: None | int = ...,
k: int = ...,
dtype: DTypeLike = ...,
order: _OrderCF = ...,
*,
device: None | L["cpu"] = ...,
like: None | _SupportsArrayFunc = ...,
) -> NDArray[Any]: ...
@overload
def diag(v: _ArrayLike[_SCT], k: int = ...) -> NDArray[_SCT]: ...
@overload
def diag(v: ArrayLike, k: int = ...) -> NDArray[Any]: ...
@overload
def diagflat(v: _ArrayLike[_SCT], k: int = ...) -> NDArray[_SCT]: ...
@overload
def diagflat(v: ArrayLike, k: int = ...) -> NDArray[Any]: ...
@overload
def tri(
N: int,
M: None | int = ...,
k: int = ...,
dtype: None = ...,
*,
like: None | _SupportsArrayFunc = ...
) -> NDArray[float64]: ...
@overload
def tri(
N: int,
M: None | int = ...,
k: int = ...,
dtype: _DTypeLike[_SCT] = ...,
*,
like: None | _SupportsArrayFunc = ...
) -> NDArray[_SCT]: ...
@overload
def tri(
N: int,
M: None | int = ...,
k: int = ...,
dtype: DTypeLike = ...,
*,
like: None | _SupportsArrayFunc = ...
) -> NDArray[Any]: ...
@overload
def tril(v: _ArrayLike[_SCT], k: int = ...) -> NDArray[_SCT]: ...
@overload
def tril(v: ArrayLike, k: int = ...) -> NDArray[Any]: ...
@overload
def triu(v: _ArrayLike[_SCT], k: int = ...) -> NDArray[_SCT]: ...
@overload
def triu(v: ArrayLike, k: int = ...) -> NDArray[Any]: ...
def vander(
x: _ArrayLikeInt_co,
N: None | int = ...,
increasing: bool = ...,
N: None | int = ...,
increasing: bool = ...,
这段代码定义了两个变量 `N` 和 `increasing`。在类型注释中,`N` 的类型是可空的整数或者 `None`,而 `increasing` 是布尔类型。这些变量的具体值在这里用 `...` 表示,实际应用中应该有具体的赋值。
@overload
def vander(
x: _ArrayLikeFloat_co,
N: None | int = ...,
increasing: bool = ...,
) -> NDArray[floating[Any]]: ...
@overload
def vander(
x: _ArrayLikeComplex_co,
N: None | int = ...,
increasing: bool = ...,
) -> NDArray[complexfloating[Any, Any]]: ...
@overload
def vander(
x: _ArrayLikeObject_co,
N: None | int = ...,
increasing: bool = ...,
) -> NDArray[object_]: ...
@overload
def histogram2d(
x: _ArrayLikeFloat_co,
y: _ArrayLikeFloat_co,
bins: int | Sequence[int] = ...,
range: None | _ArrayLikeFloat_co = ...,
density: None | bool = ...,
weights: None | _ArrayLikeFloat_co = ...,
) -> tuple[
NDArray[float64],
NDArray[floating[Any]],
NDArray[floating[Any]],
]: ...
@overload
def histogram2d(
x: _ArrayLikeComplex_co,
y: _ArrayLikeComplex_co,
bins: int | Sequence[int] = ...,
range: None | _ArrayLikeFloat_co = ...,
density: None | bool = ...,
weights: None | _ArrayLikeFloat_co = ...,
) -> tuple[
NDArray[float64],
NDArray[complexfloating[Any, Any]],
NDArray[complexfloating[Any, Any]],
]: ...
@overload
def histogram2d(
x: _ArrayLikeComplex_co,
y: _ArrayLikeComplex_co,
bins: Sequence[_ArrayLikeInt_co],
range: None | _ArrayLikeFloat_co = ...,
density: None | bool = ...,
weights: None | _ArrayLikeFloat_co = ...,
) -> tuple[
NDArray[float64],
NDArray[Any],
NDArray[Any],
]: ...
@overload
def mask_indices(
n: int,
mask_func: _MaskFunc[int],
k: int = ...,
) -> tuple[NDArray[intp], NDArray[intp]]: ...
@overload
def mask_indices(
n: int,
mask_func: _MaskFunc[_T],
k: _T,
) -> tuple[NDArray[intp], NDArray[intp]]: ...
def tril_indices(
n: int,
k: int = ...,
m: None | int = ...,
) -> tuple[NDArray[int_], NDArray[int_]]: ...
def tril_indices_from(
arr: NDArray[Any],
k: int = ...,
) -> tuple[NDArray[int_], NDArray[int_]]: ...
def triu_indices(
n: int,
k: int = ...,
m: None | int = ...,
) -> tuple[NDArray[int_], NDArray[int_]]: ...
def triu_indices_from(
arr: NDArray[Any],
k: int = ...,
) -> tuple[NDArray[int_], NDArray[int_]]: ...
.\numpy\numpy\lib\_type_check_impl.py
"""Automatically adapted for numpy Sep 19, 2005 by convertcode.py
"""
import functools
__all__ = ['iscomplexobj', 'isrealobj', 'imag', 'iscomplex',
'isreal', 'nan_to_num', 'real', 'real_if_close',
'typename', 'mintypecode',
'common_type']
from .._utils import set_module
import numpy._core.numeric as _nx
from numpy._core.numeric import asarray, asanyarray, isnan, zeros
from numpy._core import overrides, getlimits
from ._ufunclike_impl import isneginf, isposinf
array_function_dispatch = functools.partial(
overrides.array_function_dispatch, module='numpy')
@set_module('numpy')
def mintypecode(typechars, typeset='GDFgdf', default='d'):
"""
Return the character for the minimum-size type to which given types can
be safely cast.
The returned type character must represent the smallest size dtype such
that an array of the returned type can handle the data from an array of
all types in `typechars` (or if `typechars` is an array, then its
dtype.char).
Parameters
----------
typechars : list of str or array_like
If a list of strings, each string should represent a dtype.
If array_like, the character representation of the array dtype is used.
typeset : str or list of str, optional
The set of characters that the returned character is chosen from.
The default set is 'GDFgdf'.
default : str, optional
The default character, this is returned if none of the characters in
`typechars` matches a character in `typeset`.
Returns
-------
typechar : str
The character representing the minimum-size type that was found.
See Also
--------
dtype
Examples
--------
>>> np.mintypecode(['d', 'f', 'S'])
'd'
>>> x = np.array([1.1, 2-3.j])
>>> np.mintypecode(x)
'D'
>>> np.mintypecode('abceh', default='G')
'G'
"""
typecodes = ((isinstance(t, str) and t) or asarray(t).dtype.char
for t in typechars)
intersection = set(t for t in typecodes if t in typeset)
if not intersection:
return default
if 'F' in intersection and 'd' in intersection:
return 'D'
return min(intersection, key=_typecodes_by_elsize.index)
def _real_dispatcher(val):
return (val,)
@array_function_dispatch(_real_dispatcher)
def real(val):
"""
Return the real part of the complex argument.
Parameters
----------
val : array_like
Input array.
Returns
-------
out : ndarray or scalar
The real component of the complex argument. If `val` is real, the type
of `val` is used for the output. If `val` has complex elements, the
returned type is float.
See Also
--------
real_if_close, imag, angle
Examples
--------
>>> a = np.array([1+2j, 3+4j, 5+6j])
>>> a.real
array([1., 3., 5.])
>>> a.real = 9
>>> a
"""
return _nx.real(val)
>>> array([9.+2.j, 9.+4.j, 9.+6.j])
>>> a.real = np.array([9, 8, 7])
>>> a
>>> array([9.+2.j, 8.+4.j, 7.+6.j])
>>> np.real(1 + 1j)
"""
# 尝试获取参数 val 的实部,若无法获取则将 val 转换为 numpy 数组后再获取其实部
try:
return val.real
except AttributeError:
return asanyarray(val).real
# 定义一个辅助函数 _imag_dispatcher,接受一个参数 val,返回一个包含 val 的元组
def _imag_dispatcher(val):
return (val,)
# 使用 array_function_dispatch 装饰器,将 _imag_dispatcher 作为分派函数
@array_function_dispatch(_imag_dispatcher)
# 定义 imag 函数,用于返回复数参数的虚部
def imag(val):
"""
返回复数参数的虚部。
Parameters
----------
val : array_like
输入数组。
Returns
-------
out : ndarray or scalar
复数参数的虚部。如果 val 是实数,则输出与 val 相同的类型。如果 val 包含复数元素,返回的类型是 float。
See Also
--------
real, angle, real_if_close
Examples
--------
>>> a = np.array([1+2j, 3+4j, 5+6j])
>>> a.imag
array([2., 4., 6.])
>>> a.imag = np.array([8, 10, 12])
>>> a
array([1. +8.j, 3.+10.j, 5.+12.j])
>>> np.imag(1 + 1j)
1.0
"""
try:
return val.imag # 尝试返回 val 的虚部属性
except AttributeError:
return asanyarray(val).imag # 如果 val 没有 imag 属性,将其转换为数组后再获取虚部
# 定义一个辅助函数 _is_type_dispatcher,接受一个参数 x,返回一个包含 x 的元组
def _is_type_dispatcher(x):
return (x,)
# 使用 array_function_dispatch 装饰器,将 _is_type_dispatcher 作为分派函数
@array_function_dispatch(_is_type_dispatcher)
# 定义 iscomplex 函数,返回一个布尔数组,指示输入元素是否为复数
def iscomplex(x):
"""
返回一个布尔数组,其中元素为 True 表示输入元素是复数。
检测的是输入元素是否具有非零虚部,而不是输入类型是否为复数。
Parameters
----------
x : array_like
输入数组。
Returns
-------
out : ndarray of bools
输出布尔数组。
See Also
--------
isreal
iscomplexobj : 如果 x 是复数类型或复数数组,则返回 True。
Examples
--------
>>> np.iscomplex([1+1j, 1+0j, 4.5, 3, 2, 2j])
array([ True, False, False, False, False, True])
"""
ax = asanyarray(x) # 将 x 转换为数组
if issubclass(ax.dtype.type, _nx.complexfloating): # 如果数组的类型是复数浮点类型
return ax.imag != 0 # 返回虚部非零的布尔数组
res = zeros(ax.shape, bool) # 创建与 ax 形状相同的布尔数组
return res[()] # 将其转换为标量(如果需要)
# 使用 array_function_dispatch 装饰器,将 _is_type_dispatcher 作为分派函数
@array_function_dispatch(_is_type_dispatcher)
# 定义 isreal 函数,返回一个布尔数组,指示输入元素是否为实数
def isreal(x):
"""
返回一个布尔数组,其中元素为 True 表示输入元素是实数。
如果元素具有复数类型且虚部为零,则该元素的返回值为 True。
Parameters
----------
x : array_like
输入数组。
Returns
-------
out : ndarray, bool
与 x 相同形状的布尔数组。
Notes
-----
对于字符串或对象数组,isreal 可能会产生意外结果(见示例)。
See Also
--------
iscomplex
isrealobj : 如果 x 不是复数类型,则返回 True。
Examples
--------
>>> a = np.array([1+1j, 1+0j, 4.5, 3, 2, 2j], dtype=complex)
>>> np.isreal(a)
array([False, True, True, True, True, False])
函数不适用于字符串数组。
>>> a = np.array([2j, "a"], dtype="U")
>>> np.isreal(a)
False
对于 ``dtype=object`` 的输入数组,即使其中任何元素是复数,也会返回 True。
>>> a = np.array([1, "2", 3+4j], dtype=object)
>>> np.isreal(a)
array([ True, True, True])
"""
isreal should not be used with object arrays
# 创建一个包含复数对象的 NumPy 数组
a = np.array([1+2j, 2+1j], dtype=object)
# 检查数组中每个元素是否为实数,但不建议在对象数组上使用该函数
np.isreal(a)
# 返回一个布尔数组,表示每个元素是否为实数
"""
返回 x 的虚部是否全为零的布尔值数组
"""
return imag(x) == 0
@array_function_dispatch(_is_type_dispatcher)
# 使用 array_function_dispatch 装饰器来分派函数调用,以便根据输入类型调用合适的函数
def iscomplexobj(x):
"""
Check for a complex type or an array of complex numbers.
The type of the input is checked, not the value. Even if the input
has an imaginary part equal to zero, `iscomplexobj` evaluates to True.
Parameters
----------
x : any
The input can be of any type and shape.
Returns
-------
iscomplexobj : bool
The return value, True if `x` is of a complex type or has at least
one complex element.
See Also
--------
isrealobj, iscomplex
Examples
--------
>>> np.iscomplexobj(1)
False
>>> np.iscomplexobj(1+0j)
True
>>> np.iscomplexobj([3, 1+0j, True])
True
"""
try:
dtype = x.dtype
type_ = dtype.type
except AttributeError:
type_ = asarray(x).dtype.type
return issubclass(type_, _nx.complexfloating)
@array_function_dispatch(_is_type_dispatcher)
# 使用 array_function_dispatch 装饰器来分派函数调用,以便根据输入类型调用合适的函数
def isrealobj(x):
"""
Return True if x is a not complex type or an array of complex numbers.
The type of the input is checked, not the value. So even if the input
has an imaginary part equal to zero, `isrealobj` evaluates to False
if the data type is complex.
Parameters
----------
x : any
The input can be of any type and shape.
Returns
-------
y : bool
The return value, False if `x` is of a complex type.
See Also
--------
iscomplexobj, isreal
Notes
-----
The function is only meant for arrays with numerical values but it
accepts all other objects. Since it assumes array input, the return
value of other objects may be True.
>>> np.isrealobj('A string')
True
>>> np.isrealobj(False)
True
>>> np.isrealobj(None)
True
Examples
--------
>>> np.isrealobj(1)
True
>>> np.isrealobj(1+0j)
False
>>> np.isrealobj([3, 1+0j, True])
False
"""
return not iscomplexobj(x)
#-----------------------------------------------------------------------------
def _getmaxmin(t):
# 从 numpy._core 导入 getlimits 函数
from numpy._core import getlimits
# 调用 getlimits.finfo 函数,传入类型 t
f = getlimits.finfo(t)
# 返回 f 的最大值和最小值
return f.max, f.min
def _nan_to_num_dispatcher(x, copy=None, nan=None, posinf=None, neginf=None):
# 返回一个元组 (x,),用于分派 nan_to_num 函数的调用
return (x,)
@array_function_dispatch(_nan_to_num_dispatcher)
# 使用 array_function_dispatch 装饰器来分派函数调用,以便根据输入类型调用合适的函数
def nan_to_num(x, copy=True, nan=0.0, posinf=None, neginf=None):
"""
Replace NaN with zero and infinity with large finite numbers (default
behaviour) or with the numbers defined by the user using the `nan`,
`posinf` and/or `neginf` keywords.
If `x` is inexact, NaN is replaced by zero or by the user defined value in
`nan` keyword, infinity is replaced by the largest finite floating point
values representable by ``x.dtype`` or by the user defined value in
`posinf` keyword and -infinity is replaced by the most negative finite
floating point values representable by ``x.dtype`` or by the user defined
value in `neginf` keyword.
"""
# 将输入数据 `x` 转换为 NumPy 数组,保留子类信息并根据 `copy` 参数决定是否复制数据
x = _nx.array(x, subok=True, copy=copy)
# 获取数组 `x` 的数据类型
xtype = x.dtype.type
# 检查 x 是否为标量(即维度为 0)
isscalar = (x.ndim == 0)
# 如果 x 的类型不是浮点数或复数类型的子类,则根据是否是标量返回 x 的值或单个元素
if not issubclass(xtype, _nx.inexact):
return x[()] if isscalar else x
# 检查 x 的类型是否为复数类型的子类
iscomplex = issubclass(xtype, _nx.complexfloating)
# 如果 x 是复数类型,则将 x 分成实部和虚部,否则将 x 放入一个元组中
dest = (x.real, x.imag) if iscomplex else (x,)
# 获取 x.real 的数据类型的最大值和最小值
maxf, minf = _getmaxmin(x.real.dtype)
# 如果 posinf 不为 None,则将 maxf 设为 posinf
if posinf is not None:
maxf = posinf
# 如果 neginf 不为 None,则将 minf 设为 neginf
if neginf is not None:
minf = neginf
# 遍历 dest 中的元素 d
for d in dest:
# 找到 d 中的 NaN 值的索引
idx_nan = isnan(d)
# 找到 d 中的正无穷值的索引
idx_posinf = isposinf(d)
# 找到 d 中的负无穷值的索引
idx_neginf = isneginf(d)
# 将 NaN 的位置替换为 nan
_nx.copyto(d, nan, where=idx_nan)
# 将正无穷的位置替换为 maxf
_nx.copyto(d, maxf, where=idx_posinf)
# 将负无穷的位置替换为 minf
_nx.copyto(d, minf, where=idx_neginf)
# 根据是否是标量返回 x 的值或单个元素
return x[()] if isscalar else x
#-----------------------------------------------------------------------------
# 定义一个私有函数 _real_if_close_dispatcher,用于分发输入参数 a 和 tol
def _real_if_close_dispatcher(a, tol=None):
# 返回一个包含参数 a 的元组
return (a,)
# 使用 array_function_dispatch 装饰器,将 _real_if_close_dispatcher 注册为 real_if_close 的分发函数
@array_function_dispatch(_real_if_close_dispatcher)
def real_if_close(a, tol=100):
"""
如果输入的数组是复数且所有虚部接近零,则返回实部。
“接近零”的定义是 `tol` 乘以 `a` 的类型的机器 epsilon。
Parameters
----------
a : array_like
输入数组。
tol : float
数组中元素的虚部的机器 epsilon 的容差。如果容差 <=1,则使用绝对容差。
Returns
-------
out : ndarray
如果 `a` 是实数,则输出与 `a` 相同的类型。如果 `a` 包含复数元素,则输出类型为 float。
See Also
--------
real, imag, angle
Notes
-----
机器 epsilon 因计算机和数据类型而异,但大多数平台上的 Python 浮点数的机器 epsilon 等于
2.2204460492503131e-16。您可以使用 'np.finfo(float).eps' 打印出浮点数的机器 epsilon。
Examples
--------
>>> np.finfo(float).eps
2.2204460492503131e-16
>>> np.real_if_close([2.1 + 4e-14j, 5.2 + 3e-15j], tol=1000)
array([2.1, 5.2])
>>> np.real_if_close([2.1 + 4e-13j, 5.2 + 3e-15j], tol=1000)
array([2.1+4.e-13j, 5.2 + 3e-15j])
"""
# 将输入参数转换为 ndarray 类型
a = asanyarray(a)
# 获取数组元素的数据类型
type_ = a.dtype.type
# 如果数据类型不是复数类型,则直接返回数组 a
if not issubclass(type_, _nx.complexfloating):
return a
# 如果指定的容差 tol 大于 1,则使用数据类型的机器 epsilon 乘以 tol 作为新的容差值
if tol > 1:
f = getlimits.finfo(type_)
tol = f.eps * tol
# 如果数组 a 的所有元素的虚部的绝对值均小于 tol,则将数组 a 转换为实部数组
if _nx.all(_nx.absolute(a.imag) < tol):
a = a.real
# 返回处理后的数组 a
return a
#-----------------------------------------------------------------------------
# 将数据类型代码映射到其描述的字典
_namefromtype = {'S1': 'character',
'?': 'bool',
'b': 'signed char',
'B': 'unsigned char',
'h': 'short',
'H': 'unsigned short',
'i': 'integer',
'I': 'unsigned integer',
'l': 'long integer',
'L': 'unsigned long integer',
'q': 'long long integer',
'Q': 'unsigned long long integer',
'f': 'single precision',
'd': 'double precision',
'g': 'long precision',
'F': 'complex single precision',
'D': 'complex double precision',
'G': 'complex long double precision',
'S': 'string',
'U': 'unicode',
'V': 'void',
'O': 'object'
}
# 使用 set_module 装饰器将函数 typename 设置为属于 'numpy' 模块的函数
@set_module('numpy')
def typename(char):
"""
根据给定的数据类型代码返回描述信息。
Parameters
----------
char : str
数据类型代码。
Returns
-------
out : str
给定数据类型代码的描述信息。
See Also
--------
dtype
"""
Examples
--------
# 定义一个类型字符列表,包含多种数据类型的表示符号
>>> typechars = ['S1', '?', 'B', 'D', 'G', 'F', 'I', 'H', 'L', 'O', 'Q',
... 'S', 'U', 'V', 'b', 'd', 'g', 'f', 'i', 'h', 'l', 'q']
# 遍历每个类型字符,并输出其对应的类型名称
>>> for typechar in typechars:
... print(typechar, ' : ', np.typename(typechar))
...
S1 : character
? : bool
B : unsigned char
D : complex double precision
G : complex long double precision
F : complex single precision
I : unsigned integer
H : unsigned short
L : unsigned long integer
O : object
Q : unsigned long long integer
S : string
U : unicode
V : void
b : signed char
d : double precision
g : long precision
f : single precision
i : integer
h : short
l : long integer
q : long long integer
"""
return _namefromtype[char]
array_type = [[_nx.float16, _nx.float32, _nx.float64, _nx.longdouble],
[None, _nx.complex64, _nx.complex128, _nx.clongdouble]]
array_precision = {_nx.float16: 0,
_nx.float32: 1,
_nx.float64: 2,
_nx.longdouble: 3,
_nx.complex64: 1,
_nx.complex128: 2,
_nx.clongdouble: 3}
def _common_type_dispatcher(*arrays):
return arrays
@array_function_dispatch(_common_type_dispatcher)
def common_type(*arrays):
"""
Return a scalar type which is common to the input arrays.
The return type will always be an inexact (i.e. floating point) scalar
type, even if all the arrays are integer arrays. If one of the inputs is
an integer array, the minimum precision type that is returned is a
64-bit floating point dtype.
All input arrays except int64 and uint64 can be safely cast to the
returned dtype without loss of information.
Parameters
----------
array1, array2, ... : ndarrays
Input arrays.
Returns
-------
out : data type code
Data type code.
See Also
--------
dtype, mintypecode
Examples
--------
>>> np.common_type(np.arange(2, dtype=np.float32))
<class 'numpy.float32'>
>>> np.common_type(np.arange(2, dtype=np.float32), np.arange(2))
<class 'numpy.float64'>
>>> np.common_type(np.arange(4), np.array([45, 6.j]), np.array([45.0]))
<class 'numpy.complex128'>
"""
is_complex = False
precision = 0
for a in arrays:
t = a.dtype.type
if iscomplexobj(a):
is_complex = True
if issubclass(t, _nx.integer):
p = 2
else:
p = array_precision.get(t, None)
if p is None:
raise TypeError("can't get common type for non-numeric array")
precision = max(precision, p)
if is_complex:
return array_type[1][precision]
else:
return array_type[0][precision]
.\numpy\numpy\lib\_type_check_impl.pyi
from collections.abc import Container, Iterable
from typing import (
Literal as L,
Any,
overload,
TypeVar,
Protocol,
)
import numpy as np
from numpy import (
dtype,
generic,
floating,
float64,
complexfloating,
integer,
)
from numpy._typing import (
ArrayLike,
DTypeLike,
NBitBase,
NDArray,
_64Bit,
_SupportsDType,
_ScalarLike_co,
_ArrayLike,
_DTypeLikeComplex,
)
_T = TypeVar("_T")
_T_co = TypeVar("_T_co", covariant=True)
_SCT = TypeVar("_SCT", bound=generic)
class _SupportsReal(Protocol[_T_co]):
@property
def real(self) -> _T_co: ...
class _SupportsImag(Protocol[_T_co]):
@property
def imag(self) -> _T_co: ...
def mintypecode(
typechars: Iterable[str | ArrayLike],
typeset: Container[str] = ...,
default: str = ...,
) -> str: ...
@overload
def real(val: _SupportsReal[_T]) -> _T: ...
@overload
def real(val: ArrayLike) -> NDArray[Any]: ...
@overload
def imag(val: _SupportsImag[_T]) -> _T: ...
@overload
def imag(val: ArrayLike) -> NDArray[Any]: ...
@overload
def iscomplex(x: _ScalarLike_co) -> np.bool: ...
@overload
def iscomplex(x: ArrayLike) -> NDArray[np.bool]: ...
@overload
def isreal(x: _ScalarLike_co) -> np.bool: ...
@overload
def isreal(x: ArrayLike) -> NDArray[np.bool]: ...
def iscomplexobj(x: _SupportsDType[dtype[Any]] | ArrayLike) -> bool: ...
def isrealobj(x: _SupportsDType[dtype[Any]] | ArrayLike) -> bool: ...
@overload
def nan_to_num(
x: _SCT,
copy: bool = ...,
nan: float = ...,
posinf: None | float = ...,
neginf: None | float = ...,
) -> _SCT: ...
@overload
def nan_to_num(
x: _ScalarLike_co,
copy: bool = ...,
nan: float = ...,
posinf: None | float = ...,
neginf: None | float = ...,
) -> Any: ...
@overload
def nan_to_num(
x: _ArrayLike[_SCT],
copy: bool = ...,
nan: float = ...,
posinf: None | float = ...,
neginf: None | float = ...,
) -> NDArray[_SCT]: ...
@overload
def nan_to_num(
x: ArrayLike,
copy: bool = ...,
nan: float = ...,
posinf: None | float = ...,
neginf: None | float = ...,
) -> NDArray[Any]: ...
@overload
def real_if_close(
a: _ArrayLike[complexfloating[_NBit1, _NBit1]],
tol: float = ...,
) -> NDArray[floating[_NBit1]] | NDArray[complexfloating[_NBit1, _NBit1]]: ...
@overload
def real_if_close(
a: _ArrayLike[_SCT],
tol: float = ...,
) -> NDArray[_SCT]: ...
@overload
def real_if_close(
a: ArrayLike,
tol: float = ...,
) -> NDArray[Any]: ...
@overload
def typename(char: L['S1']) -> L['character']: ...
@overload
def typename(char: L['?']) -> L['bool']: ...
@overload
def typename(char: L['b']) -> L['signed char']: ...
@overload
def typename(char: L['B']) -> L['unsigned char']: ...
@overload
def typename(char: L['h']) -> L['short']: ...
@overload
def typename(char: L['H']) -> L['unsigned short']: ...
@overload
def typename(char: L['i']) -> L['integer']: ...
@overload
def typename(char: L['I']) -> L['unsigned integer']: ...
@overload
def typename(char: L['l']) -> L['long integer']: ...
@overload
def typename(char: L['L']) -> L['unsigned long integer']: ...
@overload
def typename(char: L['q']) -> L['long long integer']: ...
@overload
def typename(char: L['Q']) -> L['unsigned long long integer']: ...
@overload
def typename(char: L['f']) -> L['single precision']: ...
@overload
def typename(char: L['d']) -> L['double precision']: ...
@overload
def typename(char: L['g']) -> L['long precision']: ...
@overload
def typename(char: L['F']) -> L['complex single precision']: ...
@overload
def typename(char: L['D']) -> L['complex double precision']: ...
@overload
def typename(char: L['G']) -> L['complex long double precision']: ...
@overload
def typename(char: L['S']) -> L['string']: ...
@overload
def typename(char: L['U']) -> L['unicode']: ...
@overload
def typename(char: L['V']) -> L['void']: ...
@overload
def typename(char: L['O']) -> L['object']: ...
@overload
def common_type(
*arrays: _SupportsDType[dtype[
integer[Any]
]]
) -> type[floating[_64Bit]]: ...
@overload
def common_type(
*arrays: _SupportsDType[dtype[
floating[_NBit1]
]]
) -> type[floating[_NBit1]]: ...
@overload
def common_type(
*arrays: _SupportsDType[dtype[
integer[Any] | floating[_NBit1]
]]
) -> type[floating[_NBit1 | _64Bit]]: ...
@overload
def common_type(
*arrays: _SupportsDType[dtype[
floating[_NBit1] | complexfloating[_NBit2, _NBit2]
]]
) -> type[complexfloating[_NBit1 | _NBit2, _NBit1 | _NBit2]]: ...
@overload
def common_type(
*arrays: _SupportsDType[dtype[
integer[Any] | floating[_NBit1] | complexfloating[_NBit2, _NBit2]
]]
) -> type[complexfloating[_64Bit | _NBit1 | _NBit2, _64Bit | _NBit1 | _NBit2]]: ...
.\numpy\numpy\lib\_ufunclike_impl.py
"""
Module of functions that are like ufuncs in acting on arrays and optionally
storing results in an output array.
"""
__all__ = ['fix', 'isneginf', 'isposinf']
import numpy._core.numeric as nx
from numpy._core.overrides import array_function_dispatch
import warnings
import functools
def _dispatcher(x, out=None):
"""
A simple dispatcher function returning input and output arrays.
Parameters
----------
x : array_like
The input array to be processed.
out : ndarray, optional
A pre-allocated output array where results are stored if provided.
Returns
-------
tuple
A tuple containing input and output arrays.
"""
return (x, out)
@array_function_dispatch(_dispatcher, verify=False, module='numpy')
def fix(x, out=None):
"""
Round to nearest integer towards zero.
Round an array of floats element-wise to nearest integer towards zero.
The rounded values are returned as floats.
Parameters
----------
x : array_like
An array of floats to be rounded.
out : ndarray, optional
A location into which the result is stored. If provided, it must have
a shape that the input broadcasts to. If not provided or None, a
freshly-allocated array is returned.
Returns
-------
out : ndarray of floats
A float array with the same dimensions as the input.
If second argument is not supplied then a float array is returned
with the rounded values.
If a second argument is supplied the result is stored there.
The return value `out` is then a reference to that array.
See Also
--------
rint, trunc, floor, ceil
around : Round to given number of decimals
Examples
--------
>>> np.fix(3.14)
3.0
>>> np.fix(3)
3.0
>>> np.fix([2.1, 2.9, -2.1, -2.9])
array([ 2., 2., -2., -2.])
"""
res = nx.asanyarray(nx.ceil(x, out=out))
res = nx.floor(x, out=res, where=nx.greater_equal(x, 0))
if out is None and type(res) is nx.ndarray:
res = res[()]
return res
@array_function_dispatch(_dispatcher, verify=False, module='numpy')
def isposinf(x, out=None):
"""
Test element-wise for positive infinity, return result as bool array.
Parameters
----------
x : array_like
The input array.
out : array_like, optional
A location into which the result is stored. If provided, it must have a
shape that the input broadcasts to. If not provided or None, a
freshly-allocated boolean array is returned.
Returns
-------
out : ndarray of bools
Boolean array indicating where the input is positive infinity.
"""
pass
is_inf = nx.isinf(x)
try:
signbit = ~nx.signbit(x)
except TypeError as e:
dtype = nx.asanyarray(x).dtype
raise TypeError(f'This operation is not supported for {dtype} values '
'because it would be ambiguous.') from e
else:
return nx.logical_and(is_inf, signbit, out)
@array_function_dispatch(_dispatcher, verify=False, module='numpy')
def isneginf(x, out=None):
"""
Test element-wise for negative infinity, return result as bool array.
Parameters
----------
x : array_like
The input array.
out : array_like, optional
A location into which the result is stored. If provided, it must have a
shape that the input broadcasts to. If not provided or None, a
freshly-allocated boolean array is returned.
Returns
-------
out : ndarray
A boolean array with the same dimensions as the input.
If second argument is not supplied then a numpy boolean array is
returned with values True where the corresponding element of the
input is negative infinity and values False where the element of
the input is not negative infinity.
If a second argument is supplied the result is stored there. If the
type of that array is a numeric type the result is represented as
zeros and ones, if the type is boolean then as False and True. The
return value `out` is then a reference to that array.
See Also
--------
isinf, isposinf, isnan, isfinite
Notes
-----
NumPy uses the IEEE Standard for Binary Floating-Point for Arithmetic
(IEEE 754).
Errors result if the second argument is also supplied when x is a scalar
input, if first and second arguments have different shapes, or if the
first argument has complex values.
Examples
--------
>>> np.isneginf(-np.inf)
True
>>> np.isneginf(np.inf)
False
>>> np.isneginf([-np.inf, 0., np.inf])
array([ True, False, False])
>>> x = np.array([-np.inf, 0., np.inf])
>>> y = np.array([2, 2, 2])
>>> np.isneginf(x, y)
array([1, 0, 0])
>>> y
array([1, 0, 0])
"""
is_inf = nx.isinf(x)
try:
signbit = nx.signbit(x)
except TypeError as e:
dtype = nx.asanyarray(x).dtype
raise TypeError(f'This operation is not supported for {dtype} values '
'because it would be ambiguous.') from e
else:
return nx.logical_and(is_inf, signbit, out)
.\numpy\numpy\lib\_ufunclike_impl.pyi
from typing import Any, overload, TypeVar
import numpy as np
from numpy import floating, object_
from numpy._typing import (
NDArray,
_FloatLike_co,
_ArrayLikeFloat_co,
_ArrayLikeObject_co,
)
_ArrayType = TypeVar("_ArrayType", bound=NDArray[Any])
__all__: list[str]
@overload
def fix(
x: _FloatLike_co,
out: None = ...,
) -> floating[Any]: ...
@overload
def fix(
x: _ArrayLikeFloat_co,
out: None = ...,
) -> NDArray[floating[Any]]: ...
@overload
def fix(
x: _ArrayLikeObject_co,
out: None = ...,
) -> NDArray[object_]: ...
@overload
def fix(
x: _ArrayLikeFloat_co | _ArrayLikeObject_co,
out: _ArrayType,
) -> _ArrayType: ...
@overload
def isposinf(
x: _FloatLike_co,
out: None = ...,
) -> np.bool: ...
@overload
def isposinf(
x: _ArrayLikeFloat_co,
out: None = ...,
) -> NDArray[np.bool]: ...
@overload
def isposinf(
x: _ArrayLikeFloat_co,
out: _ArrayType,
) -> _ArrayType: ...
@overload
def isneginf(
x: _FloatLike_co,
out: None = ...,
) -> np.bool: ...
@overload
def isneginf(
x: _ArrayLikeFloat_co,
out: None = ...,
) -> NDArray[np.bool]: ...
@overload
def isneginf(
x: _ArrayLikeFloat_co,
out: _ArrayType,
) -> _ArrayType: ...
.\numpy\numpy\lib\_user_array_impl.py
"""
Container class for backward compatibility with NumArray.
The user_array.container class exists for backward compatibility with NumArray
and is not meant to be used in new code. If you need to create an array
container class, we recommend either creating a class that wraps an ndarray
or subclasses ndarray.
"""
from numpy._core import (
array, asarray, absolute, add, subtract, multiply, divide,
remainder, power, left_shift, right_shift, bitwise_and, bitwise_or,
bitwise_xor, invert, less, less_equal, not_equal, equal, greater,
greater_equal, shape, reshape, arange, sin, sqrt, transpose
)
class container:
"""
container(data, dtype=None, copy=True)
Standard container-class for easy multiple-inheritance.
Methods
-------
copy
Returns a copy of the container.
tostring
Converts the array to a string representation.
byteswap
Swaps the byte order of the array.
astype
Converts the array to the specified data type.
"""
def __init__(self, data, dtype=None, copy=True):
self.array = array(data, dtype, copy=copy)
def __repr__(self):
if self.ndim > 0:
return self.__class__.__name__ + repr(self.array)[len("array"):]
else:
return self.__class__.__name__ + "(" + repr(self.array) + ")"
def __array__(self, t=None):
if t:
return self.array.astype(t)
return self.array
def __len__(self):
return len(self.array)
def __getitem__(self, index):
return self._rc(self.array[index])
def __setitem__(self, index, value):
self.array[index] = asarray(value, self.dtype)
def __abs__(self):
return self._rc(absolute(self.array))
def __neg__(self):
return self._rc(-self.array)
def __add__(self, other):
return self._rc(self.array + asarray(other))
__radd__ = __add__
def __iadd__(self, other):
add(self.array, other, self.array)
return self
def __sub__(self, other):
return self._rc(self.array - asarray(other))
def __rsub__(self, other):
return self._rc(asarray(other) - self.array)
def __isub__(self, other):
subtract(self.array, other, self.array)
return self
def __mul__(self, other):
return self._rc(multiply(self.array, asarray(other)))
__rmul__ = __mul__
def __imul__(self, other):
multiply(self.array, other, self.array)
return self
def __div__(self, other):
return self._rc(divide(self.array, asarray(other)))
def __rdiv__(self, other):
return self._rc(divide(asarray(other), self.array))
def __idiv__(self, other):
divide(self.array, other, self.array)
return self
def __mod__(self, other):
return self._rc(remainder(self.array, other))
def __rmod__(self, other):
return self._rc(remainder(other, self.array))
def __imod__(self, other):
remainder(self.array, other, self.array)
return self
def __divmod__(self, other):
return (self._rc(divide(self.array, other)),
self._rc(remainder(self.array, other)))
def __rdivmod__(self, other):
return (self._rc(divide(other, self.array)),
self._rc(remainder(other, self.array)))
def __pow__(self, other):
return self._rc(power(self.array, asarray(other)))
def __rpow__(self, other):
return self._rc(power(asarray(other), self.array))
def __ipow__(self, other):
power(self.array, other, self.array)
return self
def __lshift__(self, other):
return self._rc(left_shift(self.array, other))
def __rshift__(self, other):
return self._rc(right_shift(self.array, other))
def __rlshift__(self, other):
return self._rc(left_shift(other, self.array))
def __rrshift__(self, other):
return self._rc(right_shift(other, self.array))
def __ilshift__(self, other):
left_shift(self.array, other, self.array)
return self
def __irshift__(self, other):
right_shift(self.array, other, self.array)
return self
def __and__(self, other):
return self._rc(bitwise_and(self.array, other))
def __rand__(self, other):
return self._rc(bitwise_and(other, self.array))
def __iand__(self, other):
bitwise_and(self.array, other, self.array)
return self
def __xor__(self, other):
return self._rc(bitwise_xor(self.array, other))
def __rxor__(self, other):
return self._rc(bitwise_xor(other, self.array))
def __ixor__(self, other):
bitwise_xor(self.array, other, self.array)
return self
def __or__(self, other):
return self._rc(bitwise_or(self.array, other))
def __ror__(self, other):
return self._rc(bitwise_or(other, self.array))
def __ior__(self, other):
bitwise_or(self.array, other, self.array)
return self
def __pos__(self):
return self._rc(self.array)
def __invert__(self):
return self._rc(invert(self.array))
def _scalarfunc(self, func):
if self.ndim == 0:
return func(self[0])
else:
raise TypeError(
"only rank-0 arrays can be converted to Python scalars.")
def __complex__(self):
return self._scalarfunc(complex)
def __float__(self):
return self._scalarfunc(float)
def __int__(self):
return self._scalarfunc(int)
def __hex__(self):
return self._scalarfunc(hex)
def __oct__(self):
return self._scalarfunc(oct)
def __lt__(self, other):
return self._rc(less(self.array, other))
def __le__(self, other):
return self._rc(less_equal(self.array, other))
def __eq__(self, other):
return self._rc(equal(self.array, other))
def __ne__(self, other):
return self._rc(not_equal(self.array, other))
def __gt__(self, other):
return self._rc(greater(self.array, other))
def __ge__(self, other):
return self._rc(greater_equal(self.array, other))
def copy(self):
""
return self._rc(self.array.copy())
def tostring(self):
""
return self.array.tostring()
def tobytes(self):
""
return self.array.tobytes()
def byteswap(self):
""
return self._rc(self.array.byteswap())
def astype(self, typecode):
""
return self._rc(self.array.astype(typecode))
def _rc(self, a):
if len(shape(a)) == 0:
return a
else:
return self.__class__(a)
def __array_wrap__(self, *args):
return self.__class__(args[0])
def __setattr__(self, attr, value):
if attr == 'array':
object.__setattr__(self, attr, value)
return
try:
self.array.__setattr__(attr, value)
except AttributeError:
object.__setattr__(self, attr, value)
def __getattr__(self, attr):
if (attr == 'array'):
return object.__getattribute__(self, attr)
return self.array.__getattribute__(attr)
if __name__ == '__main__':
temp = reshape(arange(10000), (100, 100))
ua = container(temp)
print(dir(ua))
print(shape(ua), ua.shape)
ua_small = ua[:3, :5]
print(ua_small)
ua_small[0, 0] = 10
print(ua_small[0, 0], ua[0, 0])
print(sin(ua_small) / 3. * 6. + sqrt(ua_small ** 2))
print(less(ua_small, 103), type(less(ua_small, 103)))
print(type(ua_small * reshape(arange(15), shape(ua_small))))
print(reshape(ua_small, (5, 3)))
print(transpose(ua_small))