首页 > 解决方案 > 获取等于 100 的百分比列表

问题描述

我有数据显示某个国家/地区持有的 ETF 的权重。问题是数据源的权重存在细微差异。例如,对于 ETF VTI,所有百分比的总和(美国+加拿大)为 1.026,这意味着总数约为 102%。

当我绘制或显示数据时,小的百分比差异是一个问题,当图表显示的总数 > 或 < 然后是 100% 时,这是一个外观/视觉问题

这是数据的样子:

d = {'Name': [US, US, US, CA], 'Weight': [1, 1, 1.0197, 0.0009], 'ETF': [SPY, IVV, VTI, VTI]}
df = pd.DataFrame(data=d)
df
    Name   Weight     ETF
0     US     1        SPY
1     US     1        IVV
2     US     1.0197   VTI
3     CA     0.0009   VTI

我已经编写了一些代码试图在下面解决这个问题,但我遇到了另一个问题。我编写的代码查看了实际总数和 100% 之间的差异,然后在列表中的所有值之间添加或减去该差异,如下所示。问题是,当需要减去百分比时,我最终会得到很小但仍然是负值,这是不可取的。

def re_weight(df):

     etfs= df['ETF'].unique()

     for etf in etfs: 


         l = (df[df['ETF']==etf].shape)[0]
         total = float(df[df['ETF']==etf]['Weight'].sum())
         diff = 1-total 

         filler = diff/l

         df.loc[df['ETF']==etf, 'Weight'] = df[df['ETF']==etf]['Weight']+filler


     return df

countries = pd.read_csv('output\\countries.csv')

countries[['Weight','ETF']] = re_weight(countries[['Weight','ETF']])

这是上面代码的输出,现在一切都等于 1,但我被困在某些负百分比值的地方。

df = pd.DataFrame(data=d)
df
    Name   Weight     ETF
0     US     1        SPY
1     US     1        IVV
2     US     1.0094   VTI
3     CA    -0.0094   VTI

如何格式化百分比以使它们始终总计为 100% 并且没有负值?

标签: pythonpandaslistnumpymath

解决方案


您可以groupby.transform在此处使用每行旁边的“不正确”总和,然后除以该数量进行更正。就像@ThierrLathuille 在评论中建议的那样:

print(df)
            Name  Weight  ETF
0  United States  1.0000  SPY
1  United States  1.0000  IVV
2  United States  1.0197  VTI
3         Canada  0.0009  VTI

应用上面解释的逻辑

df['weight_recalc'] = df['Weight'] / df.groupby(['ETF']).Weight.transform('sum')
print(df)
            Name  Weight  ETF  weight_recalc
0  United States  1.0000  SPY       1.000000
1  United States  1.0000  IVV       1.000000
2  United States  1.0197  VTI       0.999118
3         Canada  0.0009  VTI       0.000882

显示重新计算正确

print(df.groupby('ETF').weight_recalc.sum())
ETF
IVV    1.0
SPY    1.0
VTI    1.0
Name: weight_recalc, dtype: float64

推荐阅读