Ben S.
Ben S.

Reputation: 3545

Make a new array by repeating some rows of an old array in Julia

Suppose I have an array:

julia> a = [1 1; 2 2; 3 3; 4 4; 5 5; 6 6; 7 7;]
7×2 Array{Int64,2}:
 1  1
 2  2
 3  3
 4  4
 5  5
 6  6
 7  7

And I make a vector that specifies how many times each row gets repeated in the new array:

julia> r = [0; 2; 0; 4; 0; 1; 0;]
7-element Array{Int64,1}:
 0
 2
 0
 4
 0
 1
 0

The output that I want is:

julia> a_repeated = [2 2; 2 2; 4 4; 4 4; 4 4; 4 4; 6 6;]
7×2 Array{Int64,2}:
 2  2
 2  2
 4  4
 4  4
 4  4
 4  4
 6  6

How do I get there? I thought I would use the repeat function, but I can't seem to understand how inner and outer work.

Upvotes: 3

Views: 1473

Answers (2)

mbauman
mbauman

Reputation: 31342

Using the rep function from DataArrays.jl, this is simple and efficient. It's deprecated there, though, so I'd pull it out and define it yourself:

function rep(x::AbstractVector, lengths::AbstractVector{T}) where T <: Integer
    if length(x) != length(lengths)
        throw(DimensionMismatch("vector lengths must match"))
    end
    res = similar(x, sum(lengths))
    i = 1
    for idx in 1:length(x)
        tmp = x[idx]
        for kdx in 1:lengths[idx]
            res[i] = tmp
            i += 1
        end
    end
    return res
end

Like sample, it works on vectors and not matrices, so we do the same song and dance as in Sample rows from an array in Julia. Compute the indices of the rows and then use those to index into the matrix:

julia> idxs = rep(axes(a, 1), r)
7-element Array{Int64,1}:
 2
 2
 4
 4
 4
 4
 6

julia> a[idxs, :]
7×2 Array{Int64,2}:
 2  2
 2  2
 4  4
 4  4
 4  4
 4  4
 6  6

Upvotes: 3

Gnimuc
Gnimuc

Reputation: 8566

we can use repeat and array comprehension to get the result:

julia> a[2,:]'
1×2 Array{Int64,2}:
 2  2

# inner=(2,1)
# 2: repeat twice in the first dimension
# 1: don't repeat in the second dimension
julia> repeat(a[2,:]', inner=(2,1)) 
2×2 Array{Int64,2}:          
 2  2
 2  2

# returns empty array
julia> repeat(a[2,:]', inner=(0,1))
0×2 Array{Int64,2}

julia> vcat([repeat(a[i,:]', inner=(r[i],1)) for i in indices(a,1)]...)
7×2 Array{Int64,2}:
 2  2
 2  2
 4  4
 4  4
 4  4
 4  4
 6  6

Upvotes: 2

Related Questions