如何以 panadic 方式实现 dyadic 产品

How to implement a dyadic product in a pandaic way

我有以下数据框:

df    
    A   B
0   2.5 0.1
1   NaN 0.5
2   NaN 0.3
3   2.0 0.1

我想将 A 中的每个非值与 B 列相乘。 这可以使用

来实现
dyadic = np.multiply(df['A'].values.reshape((1,4)).T, df['B'].values.reshape((1,4)))
dyadic

和returns向量的二元积

array([[ 0.25,  1.25,  0.75,  0.25],
       [  nan,   nan,   nan,   nan],
       [  nan,   nan,   nan,   nan],
       [ 0.2 ,  1.  ,  0.6 ,  0.2 ]])

是否可以直接从pandas构建这样的DataFrame?

本题背景:经过groupby之后,每组都包含一个具有上述结构的DataFrame。 A 中总是至少有一个非 nan 条目,但也可能有多个。我想构建一个新列作为 (non-nan(A) * (B)) 向量的平均值(如果你愿意,这是某种归因,考虑到 A 值的不安全性) 这可以通过

简单地实现
np.nanmean(dyadic, axis=0)
array([ 0.225,  1.125,  0.675,  0.225])

或者 numpy 只是这里最优雅的解决方案吗?

一种方式

pd.DataFrame(columns=df.B,index=df.A).apply(lambda x : x.name*x.index)
Out[93]: 
B      0.1   0.5   0.3   0.1
A                           
 2.5  0.25  1.25  0.75  0.25
NaN    NaN   NaN   NaN   NaN
NaN    NaN   NaN   NaN   NaN
 2.0  0.20  1.00  0.60  0.20

另一种方式(应该比apply快)

df[['B']].T.reindex(list(df[['B']])*len(df)).reset_index(drop=True).mul(df.A,0)
Out[106]: 
      0     1     2     3
0  0.25  1.25  0.75  0.25
1   NaN   NaN   NaN   NaN
2   NaN   NaN   NaN   NaN
3  0.20  1.00  0.60  0.20

又名,dot 产品。

i = df[['A']].values
j = df[['B']].values.T

i.dot(j)

array([[ 0.25,  1.25,  0.75,  0.25],
       [  nan,   nan,   nan,   nan],
       [  nan,   nan,   nan,   nan],
       [ 0.2 ,  1.  ,  0.6 ,  0.2 ]])

如果您希望结果作为 DataFrame,请执行此操作 -

df[['A']].dot(df[['B']].values.T)

或者,

df[['A']].dot(df['B'].values[None, :])  # thanks to Zero for the alt

      0     1     2     3
0  0.25  1.25  0.75  0.25
1   NaN   NaN   NaN   NaN
2   NaN   NaN   NaN   NaN
3  0.20  1.00  0.60  0.20

然后您可以对结果调用 meannanmean -

df[['A']].dot(df[['B']].values.T).mean(0)

0    0.225
1    1.125
2    0.675
3    0.225
dtype: float64