世界各州的贫富差距分析
讨论问题:
一、很多媒体报道美国在过去一些年间贫富差距扩大。这里我们分析全球数据,运用数据分析全球各个州之间在过去20年间的贫富差距是扩大,减小还是维持不变。
二、以亚洲与南美数据为例分析,如果A组的平均值大于B组,是否说明最大值在A组中
1、首先,将国家和地区数据在Github上取下来:
url = "https://raw.githubusercontent.com/cs109/2014_data/master/countries.csv"
s = StringIO.StringIO(requests.get(url).content)
countries = pd.read_csv(s)
print countries.head()
CountryRegion
0AlgeriaAFRICA
1AngolaAFRICA
2BeninAFRICA
3BotswanaAFRICA
4BurkinaAFRICA
然后将国家的人均收入数据从https://www.gapminder.org/data/documentation/gd001/这个网站上取下来
income = pd.read_excel('.../indicator gapminder gdp_per_capita_ppp.xlsx',sheetname = "Data")
print income.head()
GDP per capita180018011802180318041805
0AbkhaziaNaNNaNNaNNaNNaNNaN
1Afghanistan603.0603.0603.0603.0603.0603.0
2Akrotiri and DhekeliaNaNNaNNaNNaNNaNNaN
3Albania667.0667.0668.0668.0668.0668.0
4Algeria716.0716.0717.0718.0719.0720.0
有些国家没有数据,删除缺失项
income = income.dropna(how='all')
我们想要画出某年各个国家的人均收入分布图,分布图用直方图来表示是最合适的,这里将年份作为行名更容易画各年的直方图
income.index=income[income.columns[0]] # 国家作为序号
income = income.drop(income.columns[0], axis = 1)
income.columns = map(lambda x: int(x), income.columns) # 将列名中的年份数据转为int类型,为了直接取年份
income = income.transpose()#转置
print income.head()
GDP per capitaAfghanistanAlbaniaAlgeriaAndorraAngola\
1800603.0667.0716.01197.0618.0
1801603.0667.0716.01199.0620.0
1802603.0668.0717.01201.0623.0
1803603.0668.0718.01204.0626.0
1804603.0668.0719.01206.0628.0
接下来画直方图:
year = 2000
plt.hist(income.ix[year].values, bins = 20)
plt.title('Year: %i' % year)
plt.xlabel('人均收入')
plt.ylabel('频数')
plt.show()
文章图片
image.png
可以看出人均一万美金以下的国家最多,各个国家之间的贫富差距相当大,那1万美金以下究竟是怎么分布的看不出来,将收入取log则能区分出来:
plt.hist(np.log10(income.ix[year].dropna().values), bins = 20)
plt.title('Year: %i' % year)
plt.xlabel('人均收入 (log10)')
plt.ylabel('频数')
plt.show()
文章图片
image.png
可以看出2000年时人均10000美金的国家是最多的,人均一万美金以下的分布也较广,还有人均几百美金的
接下来看各州之间的贫富差距:
2、将Country表格与income表格合并,观察两个表格可以看出共同的参数是国家名,所以以这个为主键进行合并
def mergeByYear(year):
#取出收入数据
data = https://www.it610.com/article/pd.DataFrame(income.ix[year].values, columns=['Income'])
# 拿到income的列名,作为新dataframe的Country列
data['Country'] = income.columns
joined = pd.merge(data, countries, how="inner", on=['Country'])
return joined
print mergeByYear(2000).head()
IncomeCountryRegion
0962.0AfghanistanASIA
15305.0AlbaniaEUROPE
29885.0AlgeriaAFRICA
331662.0AndorraEUROPE
43387.0AngolaAFRICA
3、画出各州的人均收入分布,这里采用箱形图来表现,箱形图可以表示数据的多种特征,如下图所示:
文章图片
image.png
文章图片
image.png
文章图片
image.png
文章图片
image.png
文章图片
image.png
文章图片
image.png
文章图片
image.png 可以看出亚洲和非洲人均收入的趋势是向上的,亚洲相比上升更多,其他州则基本保持不变。同时可以看出非洲和亚洲的奇异值相比较多,并且箱型图越来越长,说明亚洲和非洲各个国家之间的贫富差距较大,这种差距从20世纪60年代持续至今。
接下来讨论问题二:
1、如果有两组数据X和Y,都大致服从正态分布,X和Y的标准差都为1,但是X的均值大于Y的均值,计算Pr(X > a)/Pr(Y > a) 。
列出该表达式的函数:
diff是X的均值,Y的均值为0
def ratioNormals(diff,a):
X = scipy.stats.norm(loc = diff,scale = 1)
Y = scipy.stats.norm(loc = 0,scale = 1)
return X.sf(a)/Y.sf(a) #sf是生存函数,即求X>a的概率
用不同的均值差来计算概率比值:
diffs = np.linspace(0,5,50)
aa = range(2,6)
for a in aa:
ratios = [ratioNormals(diff, a) for diff in diffs]
plt.plot(diffs,ratios)
plt.legend(["a={}".format(a) for a in aa], loc=0);
plt.xlabel('Diff');
plt.ylabel('Pr(X>a) / Pr(Y>a)');
plt.title('不同差值下Pr(X>a)与Pr(Y>a)的概率比');
plt.yscale('log')
plt.show()
文章图片
image.png
可以看出,在正太分布下,当X的均值大于Y时,Pr(X>a)>Pr(Y>a),并且差值越大,两者之间的差距也越大。
2、考虑亚洲和南美的人均收入分布,计算这两个州的人均收入,哪个州的人均收入更多
利用mergeByYear函数拿到地区、国家、收入的dataframe,按照地区分组聚合,计算平均收入,可以看出亚洲的平均收入远大于南美。
merged = mergeByYear(2012).groupby('Region', as_index=False).mean()
merged = merged.loc[(merged.Region == "ASIA") | (merged.Region == "SOUTH AMERICA")]
merged.Income = np.round(merged.Income, 2)#保留小数点两位
print merged
RegionIncome
1ASIA23500.43
5SOUTH AMERICA13015.75
3、那接下来算一下人居收入大于10000美金的国家占所在州的比例,,再次看一下上面的结论是否正确。构造一个计算国家比例的函数:
def ratioCountries(groupedData, a):
#下面key指的是Region,group指代的是key所对应的分组,必须要有key指定才能找到分组信息,这里求得是各州中人均收入大于10000美金的国家占所在州国家的比例
prop = [len(group.Income[group.Income >= a]) / float(len(group.Income.dropna())) for key, group in groupedData]
z = pd.DataFrame(groupedData.mean().index, columns = ['Region'])
z['Mean'] = np.round(groupedData.mean().values,2)
z['P(X > %g)' % a] = np.round(prop, 4)
return z
df = mergeByYear(2012).groupby('Region')
df_ratio = ratioCountries(df, 1e4)
print df_ratio
RegionMeanP(X > 10000)
0AFRICA5601.220.2000
1ASIA23500.430.5676
2EUROPE30738.190.8571
3NORTH AMERICA16036.650.6500
4OCEANIA10481.150.3077
5SOUTH AMERICA13015.750.7500
把南美和亚洲提取出来:
df_ratio = df_ratio[(df_ratio.Region == 'ASIA') | (df_ratio.Region == 'SOUTH AMERICA')]
print df_ratio
RegionMeanP(X > 10000)
1ASIA23500.430.5676
5SOUTH AMERICA13015.750.7500
可以看出人均大于10000美金的国家在所在州所占比例,亚洲小于南美,这与上面的结论不一致。
4、上面可以看出亚洲国家之间的贫富差距有多大,接下来考虑一个问题,如果考虑各国人口数量,那人均收入是否会发生改变呢
比如我国和日本,我国的人均GDP8000美金,日本人均GDP35000美金,按照上面的算法,两国人均收入(8000+32000)/2,我国人均收入瞬间提升到20000美金。如果考虑两国人口呢,假设中日是一个国家,中国人口14亿,日本1亿3000万,那平均收入的计算方法为:
文章图片
image.png
N为人口,I为本国的人均收入,则上述中日两国修正后的人均收入为(8000 14+320001.3)/(14+1.3)≈10000
如此看来,计算了各国人口,这个平均值才能代表亚洲的真实水平,那接下来修正一下这个数据。这里可以将上述表达式进行拆分,只需要求出各国总收入除以整个州的人口,然后求和便能求出平均收入。
首先导入人口数据,并对其进行预处理:
#首先导入人口数据
population = pd.read_excel('.../indicator_total population with projections.xlsx',sheetname = "Data")
print population.head()
Total population10861100129013001348134913511377\
0AbkhaziaNaNNaNNaNNaNNaNNaNNaNNaN
1AfghanistanNaNNaNNaNNaNNaNNaNNaNNaN
2Akrotiri and DhekeliaNaNNaNNaNNaNNaNNaNNaNNaN
3AlbaniaNaNNaNNaNNaNNaNNaNNaNNaN
4AlgeriaNaNNaNNaNNaNNaNNaNNaNNaN
1413...2006200720082009\
0NaN...NaNNaNNaNNaN
1NaN...28420974.029145841.029839994.030577756.0
2NaN...NaNNaN15700.0NaN
3NaN...3156607.03169665.03181397.03192723.0
4NaN...33391954.033906605.034428028.034950168.0
删除全部是NAN的国家,按照上面的方法将数据进行处理,方便下面进行分组聚合。
population = population.dropna(how='all')
population = population.rename(columns = {'Total population':'Country'})#重命名
#把国家列设为index
population.index=population[population.columns[0]]
population = population.drop(population.columns[0], axis = 1)
population.columns = map(lambda x: int(x), population.columns)#将年份改为int类型
population = population.transpose()
接下来我们想把人口数据这个表格与mergeByYear这个包含人均收入,国家,地区的表格进行合并.
#将其与income,国家,地区按照国家这个主键进行合并
def mergeByYearWithPop(year):
merged_df = mergeByYear(year)
pop_df = pd.DataFrame(population.ix[year].values, columns=['Population'])
pop_df['Country'] = population.columns
joined = pd.merge(merged_df,pop_df,how="inner", on=['Country'])
#按照刚才的分析求调整后的收入,再定义一个函数,这里传入的是按地区分割的groupby对象
def func(df):
totlePop = df.sum()['Population']
df['AdjustedIncome'] = df.Income * df.Population / float(totlePop)
df.AdjustedIncome = np.round(df.AdjustedIncome, 2)
return df
return joined.groupby('Region').apply(func)
print mergeByYearWithPop(2012).head()
IncomeCountryRegionPopulationAdjustedIncome
01893.0AfghanistanASIA33397058.015.66
19811.0AlbaniaEUROPE3227373.053.43
212779.0AlgeriaAFRICA36485828.0489.77
341926.0AndorraEUROPE87518.06.19
47230.0AngolaAFRICA20162517.0153.13
得到这个dataframe后,将最后一列按照Region求和便能得出调整后的平均收入,接下来求按国家计算的平均收入和考虑人口数量的平均收入
mergeWithPop_df = mergeByYearWithPop(2012).groupby('Region').sum()
df1 = mergeByYear(2012).groupby('Region').mean()
mergeWithPop_df.Income = mergeByYear(2012).groupby('Region').mean().Income
mergeWithPop_df = mergeWithPop_df.ix[['ASIA', 'SOUTH AMERICA']]
print mergeWithPop_df
IncomePopulationAdjustedIncome
Region
ASIA23500.4324324.036626e+099717.54
SOUTH AMERICA13015.7500004.005576e+0814551.71
【世界各州的贫富差距分析】这里可以看出,亚洲在调整前的平均收入大于南美,而当考虑了人口后,平均收入小于南美。
综上所述,如果A与B都服从正太分布,那当A的平均值大于B时,Pr(X>a)>Pr(Y>a),而当讨论两个州人均收入大于10000美金的国家所占比例时得出了相反的结论,这是因为国家的人均收入不遵循正太分布。
最后考虑了各国的总人口,将州人均收入进行了调整,得出在调整前亚洲的人均收入大于南美,然后调整后反而小了,这说明亚洲国家之间的贫富差距相当大,太多奇异值使得按照国家计算时与按照人口计算时偏差太大,而南美各国间的贫富差距较小,两个数据之间差距不太大。
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 一个人的旅行,三亚
- 布丽吉特,人生绝对的赢家
- 慢慢的美丽
- 尽力
- 一个小故事,我的思考。
- 家乡的那条小河
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量