获取等于 100 的百分比列表



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

当我绘制或显示数据时,小百分比差异是一个问题,当图表显示总计为> 或

数据如下所示:

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%,并且没有负值?

您可以使用此处的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

您不需要添加或减去某些内容,因为您将通过此方法更改比例。

假设您有 3 个数据点:

US     40%
Canada 50%
Japan  30%

如您所见,总百分比为 40+50+30 = 120%。

不同值之间的比例为:

US / Canada = 40/50 = 0.8
US / Japan = 40/30 = 1.33333
Canada / Japan = 50/30 = 1.66666

现在,我们得到 120 - 100 = 20,并从每个数据点中减去其中的 1/3,我们将得到:

US    33.33333
Canada  43.33333
Japan 23.33333

现在的比例是:

US / Canada = 33.3333/43.33333 = 0.769
US / Japan = 33.3333/23.3333 = 1.428
Canada / Japan = 43.33333/23.33333 = 1.857

看?蛋白以不可预测的方式发生了变化。

因此,为了保持它们的正确性,您必须对齐数据的规模。

1) 求和所有值:

30+40+50 = 120

2) 将 100 除以求和结果:100/120 = 0.83333333

3) 将每个值乘以之前的结果(在本例中为 0.8333333):

在此示例中,我们将得到:

US     33.33333
Canada 41.66666
Japan  25

你可以检查,但我告诉你,在这种情况下比例没有改变,现在的总和等于 100(有一些四舍五入)

在伪代码中(我对熊猫数学库没有太多经验):

s = sum(df['ETF'])
df['ETF'] = df['ETF'] * 100 / s

最新更新