我有一个熊猫系列和一个熊猫多索引数据帧。
下面是这种情况的简单示例:
iterables = [['milk', 'honey', 'dates'], ['jan', 'feb', 'mar', 'apr']]
i = pd.MultiIndex.from_product(iterables, names=['good', 'month'])
xf = pd.DataFrame(index = i)
xf['price'] = np.random.randint(1, 25, xf.shape[0])
allocation_vector = pd.Series([0.3, 0.6, 0.1], index = ['milk', 'honey', 'dates'])
此数据帧表示"每个月从 1 月到 4 月的三种产品的价格"allocation_vector表示价格的某些部分份额。
我想要实现的是将分配向量乘以我的数据帧,从而得到一个索引为"jan"、"feb"、"mar"、"apr"的序列,值等于该月的点积(即:1 月、2 月、3 月、4 月各为 jan_date_price*date_pct + jan_milk_price*milk_pct + jan_honey_price*jan_pct
(
我只能用令人讨厌的迭代黑客解决方案来解决这个问题。我认为必须有一种更pythonic的方法可以做到这一点,并且我不必担心向量列与数据帧列等相乘的顺序错误。 当然,实际数据帧具有更多未参与计算的列。
第一级乘以Series.mul
然后每个第一级求和:
np.random.seed(2019)
iterables = [['milk', 'honey', 'dates'], ['jan', 'feb', 'mar', 'apr']]
i = pd.MultiIndex.from_product(iterables, names=['good', 'month'])
xf = pd.DataFrame(index = i)
xf['price'] = np.random.randint(1, 25, xf.shape[0])
print (xf)
price
good month
milk jan 9
feb 19
mar 6
apr 23
honey jan 16
feb 13
mar 11
apr 17
dates jan 17
feb 8
mar 6
apr 20
allocation_vector = pd.Series([0.3, 0.6, 0.1], index = ['milk', 'honey', 'dates'])
print (17*0.1+9*0.3+16*0.6)
14.0
s = xf['price'].mul(allocation_vector, level=0).sum(level=1)
print (s)
month
jan 14.0
feb 14.3
mar 9.0
apr 19.1
dtype: float64
或者通过Series.unstack
、转置和使用DataFrame.dot
进行整形,但输出中值的顺序会改变:
s = xf['price'].unstack().T.dot(allocation_vector)
print (s)
month
apr 19.1
feb 14.3
jan 14.0
mar 9.0
dtype: float64
您可以使用join
和groupby
的组合来实现您想要的目标,如下所示:
allocation_vector.name = 'pct'
xf = xf.join(allocation_vector, on='good')
xf['dotproduct'] = xf.price * xf.pct
print(xf)
生成的数据帧为:
price pct dotproduct
good month
milk jan 19 0.3 5.7
feb 8 0.3 2.4
mar 7 0.3 2.1
apr 15 0.3 4.5
honey jan 9 0.6 5.4
feb 10 0.6 6.0
mar 7 0.6 4.2
apr 11 0.6 6.6
dates jan 2 0.1 0.2
feb 14 0.1 1.4
mar 12 0.1 1.2
apr 7 0.1 0.7
然后,您可以使用以下方法获得所需的结果:
print(xf.groupby('month')['dotproduct'].sum())
输出为:
month
apr 11.8
feb 9.8
jan 11.3
mar 7.5