得到百分比列表等于100
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了得到百分比列表等于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%并且没有负值?
您可以在这里使用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
显示recalc是正确的
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
看到? Proportins以不可预测的方式发生了变化。
因此,为了使它们保持正确,您必须只调整数据的比例。
1)总结所有值:
30+40+50 = 120
2)除以汇总结果100:100/120 = 0.83333333
3)将每个值乘以前一个结果(在这种情况下为0.8333333):
在这个例子中,我们将得到:
US 33.33333
Canada 41.66666
Japan 25
你可以检查一下,但是我告诉你,在这种情况下,比例没有变化,而现在的summ等于100(有些舍入)
在伪代码中(我对pandas数学库没有太多经验):
s = sum(df['ETF'])
df['ETF'] = df['ETF'] * 100 / s
以上是关于得到百分比列表等于100的主要内容,如果未能解决你的问题,请参考以下文章