# Get non-crossed factor from 2 or more other in StatModels

I have factor A and B, some levels of A “crossed” with levels of B, and some is “nested”
example:

``````A = [
1 0 0
1 0 0
1 0 0
0 1 0
0 1 0
0 0 1
0 0 1]
B = [
1 0 0 0
0 1 0 0
0 1 0 0
0 0 1 0
0 0 0 1
0 0 0 1
0 0 0 1
]
``````

1-st level of A include 1-st and 2-nd of B, but 2-nd and 3-rd of A crossed with 4th of B. so I want to get

``````C = [
1 0
1 0
1 0
0 1
0 1
0 1
0 1
]
``````

Is a common way to get this product with StatModels? Or I should find crossings manually?

I made solution, but I don’t know if the solution is effective. I will be grateful for recommendations for improvement.

``````using LinearAlgebra, StatsModels, DataFrames

function noncrossmodelmatrix(m1, m2)
mx = ModelMatrix(m1).m
my = ModelMatrix(m2).m
mat = mx' * my
for n = 1:size(mat, 2)-1
for m = 1:size(mat, 1)
if mat[m, n] > 0
for c = n+1:size(mat, 2)
if mat[m, c] > 0
mat[:, n] .+= mat[:, c]
mat[:, c] .= 0
end
end
end
end
end
cols = Vector{Int}(undef, 0)
for i = 1:size(mat, 2)
if sum(mat[:, i]) > 0
push!(cols, i)
end
end
res = replace(x -> x > 0 ? 1 : 0, view(mat, :, cols))
result = mx * res
result
end

x = [1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3]
y = [1,1,1,1,2,2,2,3,3,3,4,4,4,4,4,5,5,5,5,6,6,6,6,6,7,7,7,7,7,7,7,8,8,8,8,8]
r = rand(36)
df = DataFrame(resp = r, x = x, y = y)

m1 = ModelFrame(@formula(resp ~ 0 + x), df, contrasts=Dict(:x => StatsModels.FullDummyCoding()))
m2 = ModelFrame(@formula(resp ~ 0 + y), df, contrasts=Dict(:y =>StatsModels.FullDummyCoding()))

ncm = noncrossmodelmatrix(m1, m2)
``````