Skip to content

Commit 27201e5

Browse files
authored
Improve docs for vcat, cat, etc. (#46429)
* improve docs for cat, hcat, vcat * add cross-references * spaces * tweaks in reply to own comments * fix last doctest * tweaks & simplifications + compat note for dims=Val((1,2))
1 parent 42907bf commit 27201e5

File tree

3 files changed

+116
-93
lines changed

3 files changed

+116
-93
lines changed

base/abstractarray.jl

Lines changed: 106 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1813,111 +1813,110 @@ end
18131813
"""
18141814
vcat(A...)
18151815
1816-
Concatenate along dimension 1. To efficiently concatenate a large vector of arrays,
1817-
use `reduce(vcat, x)`.
1816+
Concatenate arrays or numbers vertically. Equivalent to [`cat`](@ref)`(A...; dims=1)`,
1817+
and to the syntax `[a; b; c]`.
1818+
1819+
To concatenate a large vector of arrays, `reduce(vcat, A)` calls an efficient method
1820+
when `A isa AbstractVector{<:AbstractVecOrMat}`, rather than working pairwise.
1821+
1822+
See also [`hcat`](@ref), [`Iterators.flatten`](@ref), [`stack`](@ref).
18181823
18191824
# Examples
18201825
```jldoctest
1821-
julia> a = [1 2 3 4 5]
1822-
1×5 Matrix{Int64}:
1823-
1 2 3 4 5
1826+
julia> v = vcat([1,2], [3,4])
1827+
4-element Vector{Int64}:
1828+
1
1829+
2
1830+
3
1831+
4
18241832
1825-
julia> b = [6 7 8 9 10; 11 12 13 14 15]
1826-
2×5 Matrix{Int64}:
1827-
6 7 8 9 10
1828-
11 12 13 14 15
1833+
julia> v == vcat(1, 2, [3,4]) # accepts numbers
1834+
true
18291835
1830-
julia> vcat(a,b)
1831-
3×5 Matrix{Int64}:
1832-
1 2 3 4 5
1833-
6 7 8 9 10
1834-
11 12 13 14 15
1836+
julia> v == [1; 2; [3,4]] # syntax for the same operation
1837+
true
18351838
1836-
julia> c = ([1 2 3], [4 5 6])
1837-
([1 2 3], [4 5 6])
1839+
julia> summary(ComplexF64[1; 2; [3,4]]) # syntax for supplying the element type
1840+
"4-element Vector{ComplexF64}"
18381841
1839-
julia> vcat(c...)
1840-
2×3 Matrix{Int64}:
1841-
1 2 3
1842-
4 5 6
1842+
julia> vcat(range(1, 2, length=3)) # collects lazy ranges
1843+
3-element Vector{Float64}:
1844+
1.0
1845+
1.5
1846+
2.0
1847+
1848+
julia> two = ([10, 20, 30]', Float64[4 5 6; 7 8 9]) # row vector and a matrix
1849+
([10 20 30], [4.0 5.0 6.0; 7.0 8.0 9.0])
18431850
1844-
julia> vs = [[1, 2], [3, 4], [5, 6]]
1845-
3-element Vector{Vector{Int64}}:
1846-
[1, 2]
1847-
[3, 4]
1848-
[5, 6]
1851+
julia> vcat(two...)
1852+
3×3 Matrix{Float64}:
1853+
10.0 20.0 30.0
1854+
4.0 5.0 6.0
1855+
7.0 8.0 9.0
18491856
1850-
julia> reduce(vcat, vs)
1857+
julia> vs = [[1, 2], [3, 4], [5, 6]];
1858+
1859+
julia> reduce(vcat, vs) # more efficient than vcat(vs...)
18511860
6-element Vector{Int64}:
18521861
1
18531862
2
18541863
3
18551864
4
18561865
5
18571866
6
1867+
1868+
julia> ans == collect(Iterators.flatten(vs))
1869+
true
18581870
```
18591871
"""
18601872
vcat(X...) = cat(X...; dims=Val(1))
18611873
"""
18621874
hcat(A...)
18631875
1864-
Concatenate along dimension 2. To efficiently concatenate a large vector of arrays,
1865-
use `reduce(hcat, x)`.
1876+
Concatenate arrays or numbers horizontally. Equivalent to [`cat`](@ref)`(A...; dims=2)`,
1877+
and to the syntax `[a b c]` or `[a;; b;; c]`.
1878+
1879+
For a large vector of arrays, `reduce(hcat, A)` calls an efficient method
1880+
when `A isa AbstractVector{<:AbstractVecOrMat}`.
1881+
For a vector of vectors, this can also be written [`stack`](@ref)`(A)`.
1882+
1883+
See also [`vcat`](@ref), [`hvcat`](@ref).
18661884
18671885
# Examples
18681886
```jldoctest
1869-
julia> a = [1; 2; 3; 4; 5]
1870-
5-element Vector{Int64}:
1871-
1
1872-
2
1873-
3
1874-
4
1875-
5
1887+
julia> hcat([1,2], [3,4], [5,6])
1888+
2×3 Matrix{Int64}:
1889+
1 3 5
1890+
2 4 6
18761891
1877-
julia> b = [6 7; 8 9; 10 11; 12 13; 14 15]
1878-
5×2 Matrix{Int64}:
1879-
6 7
1880-
8 9
1881-
10 11
1882-
12 13
1883-
14 15
1884-
1885-
julia> hcat(a,b)
1886-
5×3 Matrix{Int64}:
1887-
1 6 7
1888-
2 8 9
1889-
3 10 11
1890-
4 12 13
1891-
5 14 15
1892-
1893-
julia> c = ([1; 2; 3], [4; 5; 6])
1894-
([1, 2, 3], [4, 5, 6])
1895-
1896-
julia> hcat(c...)
1897-
3×2 Matrix{Int64}:
1898-
1 4
1899-
2 5
1900-
3 6
1892+
julia> hcat(1, 2, [30 40], [5, 6, 7]') # accepts numbers
1893+
1×7 Matrix{Int64}:
1894+
1 2 30 40 5 6 7
19011895
1902-
julia> x = Matrix(undef, 3, 0) # x = [] would have created an Array{Any, 1}, but need an Array{Any, 2}
1903-
3×0 Matrix{Any}
1896+
julia> ans == [1 2 [30 40] [5, 6, 7]'] # syntax for the same operation
1897+
true
19041898
1905-
julia> hcat(x, [1; 2; 3])
1906-
3×1 Matrix{Any}:
1907-
1
1908-
2
1909-
3
1899+
julia> Float32[1 2 [30 40] [5, 6, 7]'] # syntax for supplying the eltype
1900+
1×7 Matrix{Float32}:
1901+
1.0 2.0 30.0 40.0 5.0 6.0 7.0
19101902
1911-
julia> vs = [[1, 2], [3, 4], [5, 6]]
1912-
3-element Vector{Vector{Int64}}:
1913-
[1, 2]
1914-
[3, 4]
1915-
[5, 6]
1903+
julia> ms = [zeros(2,2), [1 2; 3 4], [50 60; 70 80]];
19161904
1917-
julia> reduce(hcat, vs)
1918-
2×3 Matrix{Int64}:
1919-
1 3 5
1920-
2 4 6
1905+
julia> reduce(hcat, ms) # more efficient than hcat(ms...)
1906+
2×6 Matrix{Float64}:
1907+
0.0 0.0 1.0 2.0 50.0 60.0
1908+
0.0 0.0 3.0 4.0 70.0 80.0
1909+
1910+
julia> stack(ms) |> summary # disagrees on a vector of matrices
1911+
"2×2×3 Array{Float64, 3}"
1912+
1913+
julia> hcat(Int[], Int[], Int[]) # empty vectors, each of size (0,)
1914+
0×3 Matrix{Int64}
1915+
1916+
julia> hcat([1.1, 9.9], Matrix(undef, 2, 0)) # hcat with empty 2×0 Matrix
1917+
2×1 Matrix{Any}:
1918+
1.1
1919+
9.9
19211920
```
19221921
"""
19231922
hcat(X...) = cat(X...; dims=Val(2))
@@ -1928,34 +1927,45 @@ typed_hcat(::Type{T}, X...) where T = _cat_t(Val(2), T, X...)
19281927
"""
19291928
cat(A...; dims)
19301929
1931-
Concatenate the input arrays along the specified dimensions in the iterable `dims`. For
1932-
dimensions not in `dims`, all input arrays should have the same size, which will also be the
1933-
size of the output array along that dimension. For dimensions in `dims`, the size of the
1934-
output array is the sum of the sizes of the input arrays along that dimension. If `dims` is
1935-
a single number, the different arrays are tightly stacked along that dimension. If `dims` is
1936-
an iterable containing several dimensions, this allows one to construct block diagonal
1937-
matrices and their higher-dimensional analogues by simultaneously increasing several
1938-
dimensions for every new input array and putting zero blocks elsewhere. For example,
1939-
`cat(matrices...; dims=(1,2))` builds a block diagonal matrix, i.e. a block matrix with
1940-
`matrices[1]`, `matrices[2]`, ... as diagonal blocks and matching zero blocks away from the
1941-
diagonal.
1930+
Concatenate the input arrays along the dimensions specified in `dims`.
1931+
1932+
Along a dimension `d in dims`, the size of the output array is `sum(size(a,d) for
1933+
a in A)`.
1934+
Along other dimensions, all input arrays should have the same size,
1935+
which will also be the size of the output array along those dimensions.
1936+
1937+
If `dims` is a single number, the different arrays are tightly packed along that dimension.
1938+
If `dims` is an iterable containing several dimensions, the positions along these dimensions
1939+
are increased simultaneously for each input array, filling with zero elsewhere.
1940+
This allows one to construct block-diagonal matrices as `cat(matrices...; dims=(1,2))`,
1941+
and their higher-dimensional analogues.
1942+
1943+
The special case `dims=1` is [`vcat`](@ref), and `dims=2` is [`hcat`](@ref).
1944+
See also [`hvcat`](@ref), [`stack`](@ref), [`repeat`](@ref).
19421945
1943-
See also [`hcat`](@ref), [`vcat`](@ref), [`hvcat`](@ref), [`repeat`](@ref).
1946+
The keyword also accepts `Val(dims)`.
1947+
1948+
!!! compat "Julia 1.8"
1949+
For multiple dimensions `dims = Val(::Tuple)` was added in Julia 1.8.
19441950
19451951
# Examples
19461952
```jldoctest
1947-
julia> cat([1 2; 3 4], [pi, pi], fill(10, 2,3,1); dims=2)
1953+
julia> cat([1 2; 3 4], [pi, pi], fill(10, 2,3,1); dims=2) # same as hcat
19481954
2×6×1 Array{Float64, 3}:
19491955
[:, :, 1] =
19501956
1.0 2.0 3.14159 10.0 10.0 10.0
19511957
3.0 4.0 3.14159 10.0 10.0 10.0
19521958
1953-
julia> cat(true, trues(2,2), trues(4)', dims=(1,2))
1959+
julia> cat(true, trues(2,2), trues(4)', dims=(1,2)) # block-diagonal
19541960
4×7 Matrix{Bool}:
19551961
1 0 0 0 0 0 0
19561962
0 1 1 0 0 0 0
19571963
0 1 1 0 0 0 0
19581964
0 0 0 1 1 1 1
1965+
1966+
julia> cat(1, [2], [3;;]; dims=Val(2))
1967+
1×3 Matrix{Int64}:
1968+
1 2 3
19591969
```
19601970
"""
19611971
@inline cat(A...; dims) = _cat(dims, A...)
@@ -3064,7 +3074,7 @@ concatenated along the remaining dimensions.
30643074
For example, if `dims = [1,2]` and `A` is 4-dimensional, then `f` is called on `x = A[:,:,i,j]`
30653075
for all `i` and `j`, and `f(x)` becomes `R[:,:,i,j]` in the result `R`.
30663076
3067-
See also [`eachcol`](@ref), [`eachslice`](@ref), [`mapreduce`](@ref).
3077+
See also [`eachcol`](@ref) or [`eachslice`](@ref), used with [`map`](@ref) or [`stack`](@ref).
30683078
30693079
# Examples
30703080
```jldoctest
@@ -3084,7 +3094,7 @@ julia> A = reshape(1:30,(2,5,3))
30843094
30853095
julia> f(x::Matrix) = fill(x[1,1], 1,4); # returns a 1×4 matrix
30863096
3087-
julia> mapslices(f, A, dims=(1,2))
3097+
julia> B = mapslices(f, A, dims=(1,2))
30883098
1×4×3 Array{$Int, 3}:
30893099
[:, :, 1] =
30903100
1 1 1 1
@@ -3095,6 +3105,11 @@ julia> mapslices(f, A, dims=(1,2))
30953105
[:, :, 3] =
30963106
21 21 21 21
30973107
3108+
julia> f2(x::AbstractMatrix) = fill(x[1,1], 1,4);
3109+
3110+
julia> B == stack(f2, eachslice(A, dims=3))
3111+
true
3112+
30983113
julia> g(x) = x[begin] // x[end-1]; # returns a number
30993114
31003115
julia> mapslices(g, A, dims=[1,3])

base/reduce.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -459,8 +459,10 @@ For empty collections, providing `init` will be necessary, except for some speci
459459
neutral element of `op`.
460460
461461
Reductions for certain commonly-used operators may have special implementations, and
462-
should be used instead: `maximum(itr)`, `minimum(itr)`, `sum(itr)`, `prod(itr)`,
463-
`any(itr)`, `all(itr)`.
462+
should be used instead: [`maximum`](@ref)`(itr)`, [`minimum`](@ref)`(itr)`, [`sum`](@ref)`(itr)`,
463+
[`prod`](@ref)`(itr)`, [`any`](@ref)`(itr)`, [`all`](@ref)`(itr)`.
464+
There are efficient methods for concatenating certain arrays of arrays
465+
by calling `reduce(`[`vcat`](@ref)`, arr)` or `reduce(`[`hcat`](@ref)`, arr)`.
464466
465467
The associativity of the reduction is implementation dependent. This means that you can't
466468
use non-associative operations like `-` because it is undefined whether `reduce(-,[1,2,3])`

base/slicearray.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ the ordering of the dimensions will match those in `dims`. If `drop = false`, th
8585
`Slices` will have the same dimensionality as the underlying array, with inner
8686
dimensions having size 1.
8787
88+
See [`stack`](@ref)`(slices; dims)` for the inverse of `eachcol(A; dims::Integer, drop=true)`.
89+
8890
See also [`eachrow`](@ref), [`eachcol`](@ref), [`mapslices`](@ref) and [`selectdim`](@ref).
8991
9092
!!! compat "Julia 1.1"
@@ -131,6 +133,8 @@ end
131133
Create a [`RowSlices`](@ref) object that is a vector of rows of matrix or vector `A`.
132134
Row slices are returned as `AbstractVector` views of `A`.
133135
136+
For the inverse, see [`stack`](@ref)`(rows; dims=1)`.
137+
134138
See also [`eachcol`](@ref), [`eachslice`](@ref) and [`mapslices`](@ref).
135139
136140
!!! compat "Julia 1.1"
@@ -167,6 +171,8 @@ eachrow(A::AbstractVector) = eachrow(reshape(A, size(A,1), 1))
167171
Create a [`ColumnSlices`](@ref) object that is a vector of columns of matrix or vector `A`.
168172
Column slices are returned as `AbstractVector` views of `A`.
169173
174+
For the inverse, see [`stack`](@ref)`(cols)` or `reduce(`[`hcat`](@ref)`, cols)`.
175+
170176
See also [`eachrow`](@ref), [`eachslice`](@ref) and [`mapslices`](@ref).
171177
172178
!!! compat "Julia 1.1"

0 commit comments

Comments
 (0)