多指标系列点积

时间:2019-09-10 19:45:13

标签: python pandas-groupby

我有一个包含多个 sets 个数组的系列。

import pandas as pd

idx = ['a', 'b', 'c']
w = pd.Series(data=[10, 5, 20, 6, 8, 5], 
              index=pd.MultiIndex.from_product([['foo', 'bar'], idx]))
w
Out[5]: 
foo  a    10
     b     5
     c    20
bar  a     6
     b     8
     c     5

,因此foo是一个数组,而bar是另一个数组。我想将foobar与相关矩阵相乘。基本上我想计算(w * m * w)**.5

m = pd.DataFrame({idx[0]: [1.0, 0.5, 0.2],
                  idx[1]: [0.5, 1.0, 0.3],
                  idx[2]: [0.2, 0.3, 1.0]},
                 index=idx)

我都尝试过

 w.groupby(level=0).apply(lambda x: m.dot(x).dot(x)**.5)

 m.dot(w).dot(w)**.5

两者都导致

ValueError: matrices are not aligned

预期结果应该是

foo  26.739483914241877
bar  14.45683229480096

我猜想这与w具有多索引这一事实有关。在单个数组上执行相同的操作将获得预期的结果。

v = pd.Series(data=[10, 5, 20], index=idx)

m.dot(v).dot(v)**.5
Out[9]: 26.739483914241877

关于如何进行这项工作的任何想法?


编辑

使用一种变通方法,将multiindex的最顶层删除到一个函数中,我开始使用它。我仍然对其他也许更清洁的解决方案持开放态度。

def calc(v, m):
    # Copy v and make a new index, dropping outmost index.
    u = v.copy()
    u.index = v.index.droplevel(0)
    return m.dot(u).dot(u)**.5

w.groupby(level=0).apply(lambda x: calc(x,m))
Out[13]: 
bar    14.456832
foo    26.739484
dtype: float64

2 个答案:

答案 0 :(得分:1)

这是一种简单的方法,尽管在重塑阵列时需要一些手动操作。如果您认为此答案有用,我可以为您自动化。

# First define a simple function to be used 

def calc_dot(array, m):
    return m.dot(array).dot(array)**.5

# Then, the rest becomes trivial 
names = w.index.droplevel(1).unique()

# Note you would need to set reshape of array manually 
pd.Series([calc_dot(x, m) for x in w.values.reshape(2,3)], index = names)

答案 1 :(得分:0)

使用reshape函数将多索引序列转换为矩阵的一种更简洁的方法可能会有所帮助:

q = w.values.reshape(3,2)
q

输出变为

array([[10,  5],
       [20,  6],
       [ 8,  5]], dtype=int64)

但是,不幸的是,我无法复制该解决方案。