Home > Blockchain >  Matrix Multiplication with Multindex columns using broadcast
Matrix Multiplication with Multindex columns using broadcast

Time:01-26

I want to multiply two matrices (.dot not .mul), one of which may or may not have 2-D mutli-index columns. I have solved this for the 1-D case and the 2-D case, I feel like there should be a generalization between the two, but I can't figure it out.

Sample Data

>>> A = pd.DataFrame({'b': [1, 0], 'c': [1, 0], 'e': [0, 1]}, index=['a','d'])
>>> A
   b  c  e
0  1  1  0
1  0  0  1

>>> columns = pd.MultiIndex.from_product([['b', 'c', 'e'], ['metric1', 'metric2']])
>>> B2D = pd.DataFrame(
    [
        [22, 24, 20, 31, 29, 20],
        [12, 14, 10, 21, 24, 91]
    ],
    columns=columns
)
>>> B2D
        b               c               e        
  metric1 metric2 metric1 metric2 metric1 metric2
0      22      24      20      31      29      20
1      12      14      10      21      24      91
>>> B1D = B2D.xs('metric1', 1, 1)

Desired Result

>>> func(A, B2D)
        a               d        
  metric1 metric2 metric1 metric2
0      42      55      29      20
1      22      35      24      91
>>> func(A, B1D)
    a   d
0  42  29
1  22  24

My Version

This works for each case but not both. I hope theres a simpler way to combine these into a generalized version...

def func1D(a, b):
    return (a @ b.T).T

def func2D(a, b):
    return (B.stack(level=1) @ A.T).unstack()

Other Relevant Answers

pandas dot product on each sub frame in multi-index data frame

Pandas multiply dataframes with multiindex and overlapping index levels

CodePudding user response:

You can compute the levels to use in stack/unstack:

def func(a, b):
    levels = list(range(1, b.columns.nlevels))
    return (b.stack(level=levels) @ a.T).unstack(level=levels)

Output:

func(A, B1D)
    a   d
0  42  29
1  22  24

func(A, B2D)
        a               d        
  metric1 metric2 metric1 metric2
0      42      55      29      20
1      22      35      24      91
  • Related