Python 如果缺少列,则更改索引的权重

Python 如果缺少列,则更改索引的权重,python,pandas,numpy,average,Python,Pandas,Numpy,Average,我有一个包含不同国家(行)和4个指标(列)a、B、C和D的熊猫数据框架。 对于每个指标,我都有一个特定的权重,我用它来计算它们的加权和,比如说:权重a=0.2,权重B=0.2,权重C=0.4,权重D=0.2 这是我加权和的公式 df['W_Sum'] = Weigth_A*df['A'] + Weigth_B*df['B'] + Weigth_C*df['C'] + Weigth_D*df['D'] 然而,如果一列是NaN(在本例中假设为D),我需要将我的加权和更改为正常平均值 df['W_S

我有一个包含不同国家(行)和4个指标(列)a、B、C和D的熊猫数据框架。 对于每个指标,我都有一个特定的权重,我用它来计算它们的加权和,比如说:权重a=0.2,权重B=0.2,权重C=0.4,权重D=0.2

这是我加权和的公式

df['W_Sum'] = Weigth_A*df['A'] + Weigth_B*df['B'] + Weigth_C*df['C'] + Weigth_D*df['D']
然而,如果一列是NaN(在本例中假设为D),我需要将我的加权和更改为正常平均值

df['W_Sum'] = 0.33*df['A'] + 0.33*df['B'] + 0.33*df['C'] 
如果缺少两个,则:

df['W_Sum'] = 0.5*df['A'] + 0.5*df['B']
由于我不确定每个国家的哪个列会缺少值,有没有办法使这个过程自动化

谢谢

您可以使用:

wa = 0.2*df.A + 0.4*df.B + 0.2*df.C
df['new_col'] = np.where(df.isna().any(axis=1), df.mean(axis=1), wa)
范例

细节

np.其中
将根据条件的结果在平均值或加权平均值中进行选择:

df.assign(has_nans = df.isna().any(axis=1), mean=df.mean(axis=1), weighted_av = wa)

   A  B    C  new_col  has_nans  mean  weighted_av
0  1  4  7.0      3.2     False  3.80          3.2
1  2  5  8.0      4.0     False  4.75          4.0
2  3  6  NaN      4.5      True  4.50          NaN
我本来打算写一个与雅图基本相同的答案,但我想提高一点效率

import pandas as pd
import numpy as np
df = pd.DataFrame({'A':[1,2,3],
                   'B':[4,5,6],
                   'C':[7,8,np.nan],
                   'D':[1, np.nan, np.nan]})
weights = np.array([0.2,0.4,0.2,0.2])

df["w_avg"]= np.where(df.isnull().any(1),
                      df.mean(1),
                      np.dot(df.values, weights))
考虑到计算你不打算使用的东西是没有意义的

使用
np.dot
而不是手动计算
wa
的虚拟df在速度和通用性方面更好

n = 5000
df = pd.DataFrame({"A":np.random.rand(n),
                   "B": np.random.rand(n),
                   "C":np.random.rand(n),
                   "D":np.random.rand(n)})

%%timeit
wa = 0.2*df.A + 0.4*df.B + 0.2*df.C + 0.2* df.D
735 µs ± 19.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)


%%timeit
wa = np.dot(df.values, weights)
18.9 µs ± 732 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
n = 5000
df = pd.DataFrame({"A":np.random.rand(n),
                   "B": np.random.rand(n),
                   "C":np.random.rand(n),
                   "D":np.random.rand(n)})

%%timeit
wa = 0.2*df.A + 0.4*df.B + 0.2*df.C + 0.2* df.D
735 µs ± 19.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)


%%timeit
wa = np.dot(df.values, weights)
18.9 µs ± 732 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)