项目目的:通过对2012美国总统竞选赞助数据分析,得出哪个总统更具有优势的结论
项目流程:数据载入、数据清洗、数据聚合分组以及可视化
项目地址:https://tianchi.aliyun.com/notebook-ai/detail?postId=10585
一、导入数据
1.数据载入
导入需要用到的库numpy、pandas、matplotlib.pyplot
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
用pd.read_scv
来导入存储在csv中的数据。
data_01 = pd.read_csv('D:\mycode\python\study\data\data_01.csv')#用pd.read_csv读取数据
data_02 = pd.read_csv('D:\mycode\python\study\data\data_02.csv')
data_03 = pd.read_csv('D:\mycode\python\study\data\data_03.csv')
2.数据合并
用pd.concat
对数据进行拼接。
data = pd.concat([data_01, data_02, data_03])#可以将三份数据拼在一起
用head()
函数对数据前五行进行查看
data.head()#查看前五行数据
数据各字段的含义:
- cand_nm – 接受捐赠的候选人姓名
- contbr_nm – 捐赠人姓名
- contbr_st – 捐赠人所在州
- contbr_employer – 捐赠人所在公司
- contbr_occupation – 捐赠人职业
- contb_receipt_amt – 捐赠数额(美元)
- contb_receipt_dt – 收到捐款的日期
用info()
对数据进行数据类型的查看
data.info()#查看数据的信息,每个字段的名称、非空数量、数据的类型
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1001733 entries, 0 to 1730
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 cand_nm 1001733 non-null object
1 contbr_nm 1001733 non-null object
2 contbr_st 1001729 non-null object
3 contbr_employer 988004 non-null object
4 contbr_occupation 993303 non-null object
5 contb_receipt_amt 1001733 non-null float64
6 contb_receipt_dt 1001733 non-null object
dtypes: float64(1), object(6)
memory usage: 61.1+ MB
分析数据信息可知捐赠人职业和公司的两个数据有很大一部分的缺失。
用describe()
可以得知统计通用的概述值。
data.describe() #用统计学指标反应数据的概况,count非空数据、mean平均值、std标准差,后面为四分位数
二、数据清洗
1.缺失值处理
用fillna
函数可以将数据中的NULL值转化为自己想要的值,其中inplace
的值决定了直接覆盖还是创建副本。
data['contbr_employer'].fillna('NOT PROVIDED',inplace = True)#将数据集中的NULL用NOT PROVIDED代替,True代表直接修改原对象
data['contbr_occupation'].fillna('NOT PROVIDED',inplace = True)
2.数据转换
unique()
函数是去重函数,其中format
函数是将数值传入{}之中。
print('共有{}位候选人,分别是'.format(len(data['cand_nm'].unique())))#unique是将重复的去除
data['cand_nm'].unique()
因为有些候选人是来自于同一个党派的,所以可以新增一列党派。
#通过搜索引擎等途径,获取到每个总统候选人的所属党派,建立字典parties,候选人名字作为键,所属党派作为对应的值
parties = {'Bachmann, Michelle': 'Republican',
'Cain, Herman': 'Republican',
'Gingrich, Newt': 'Republican',
'Huntsman, Jon': 'Republican',
'Johnson, Gary Earl': 'Republican',
'McCotter, Thaddeus G': 'Republican',
'Obama, Barack': 'Democrat',
'Paul, Ron': 'Republican',
'Pawlenty, Timothy': 'Republican',
'Perry, Rick': 'Republican',
"Roemer, Charles E. 'Buddy' III": 'Republican',
'Romney, Mitt': 'Republican',
'Santorum, Rick': 'Republican'}
通过候选人的姓名为key
值,用map()
查询字典获得其党派存入党派列。通过value_counts
对候选人所属党派进行统计。
data['party'] = data['cand_nm'].map(parties)#在data中增加一列存储党派,用map查询parties
data['party'].value_counts()#对党派的数据进行统计
将数据根据捐赠人的职业进行划分,统计每个职业的捐赠数额,ascending=False
表示为倒序。
#根据职业对数据进行
data.groupby('contbr_occupation')['contb_receipt_amt'].sum().sort_values(ascending=False)[:20]
contbr_occupation
RETIRED 48176647.00
ATTORNEY 18470473.30
HOMEMAKER 17484807.65
INFORMATION REQUESTED PER BEST EFFORTS 15859514.55
INFORMATION REQUESTED 8742357.59
PHYSICIAN 7224044.40
PRESIDENT 6347843.59
EXECUTIVE 5273717.90
CONSULTANT 4932627.98
NOT PROVIDED 4224760.39
CEO 3570942.20
LAWYER 3537982.19
OWNER 3278488.16
INVESTOR 3204481.92
ENGINEER 2730527.43
PROFESSOR 2458033.81
C.E.O. 2433218.11
SELF-EMPLOYED 2259150.94
MANAGER 2167571.47
REAL ESTATE 2110499.34
Name: contb_receipt_amt, dtype: float64
因为一些职业的名称不一样,但是却是同一个职业,所以对data
中的数据进行循环去重。
occupation_map = {
'INFORMATION REQUESTED PER BEST EFFORTS':'NOT PROVIDED',
'INFORMATION REQUESTED':'NOT PROVIDED',
'SELF' : 'SELF-EMPLOYED',
'SELF EMPLOYED' : 'SELF-EMPLOYED',
'C.E.O.':'CEO',
'LAWYER':'ATTORNEY',
}
f = lambda x: occupation_map.get(x,x)
data.contbr_occupation = data.contbr_occupation.map(f)#对职业信息进行查询,进行去重
对雇主的数据进行类似的处理。
emp_mapping = {
'INFORMATION REQUESTED PER BEST EFFORTS' : 'NOT PROVIDED',
'INFORMATION REQUESTED' : 'NOT PROVIDED',
'SELF' : 'SELF-EMPLOYED',
'SELF EMPLOYED' : 'SELF-EMPLOYED',
}
f = lambda x: emp_mapping.get(x,x)
data.contbr_employer = data.contbr_employer.map(f)
3.数据筛选
因为赞助还包括退款(负的),所以为了简化过程,只需要为正的
data = data[data['contb_receipt_amt']>0]
根据捐助人的姓名分组,进行金额的总和,倒叙排序
data.groupby('cand_nm')['contb_receipt_amt'].sum().sort_values(ascending = False)
从下方输出的结果来看,obama和romney的支持率是最高的,因此选择这两个来分析
cand_nm
Obama, Barack 1.358776e+08
Romney, Mitt 8.833591e+07
Paul, Ron 2.100962e+07
Perry, Rick 2.030675e+07
Gingrich, Newt 1.283277e+07
Santorum, Rick 1.104316e+07
Cain, Herman 7.101082e+06
Pawlenty, Timothy 6.004819e+06
Huntsman, Jon 3.330373e+06
Bachmann, Michelle 2.711439e+06
Johnson, Gary Earl 5.669616e+05
Roemer, Charles E. 'Buddy' III 3.730099e+05
McCotter, Thaddeus G 3.903000e+04
Name: contb_receipt_amt, dtype: float64
将两个人的数据组合成一个新的数据集
data_vs = data[data['cand_nm'].isin(['Obama, Barack','Romney, Mitt'])].copy()
#将最主要的两个竞争人的数据集进行复制
4.面元化数据
对两个数据中不同的捐助金额,分别打上标签
bins = np.array([0,1,10,100,1000,10000,100000,1000000,10000000])
labels = pd.cut(data_vs['contb_receipt_amt'],bins)
labels#根据捐助的金额打上标签
411 (10, 100]
412 (100, 1000]
413 (100, 1000]
414 (10, 100]
415 (10, 100]
...
201381 (10, 100]
201382 (100, 1000]
201383 (1, 10]
201384 (10, 100]
201385 (100, 1000]
Name: contb_receipt_amt, Length: 694283, dtype: category
Categories (8, interval[int64]): [(0, 1] < (1, 10] < (10, 100] < (100, 1000] < (1000, 10000] < (10000, 100000] < (100000, 1000000] < (1000000, 10000000]]
三、数据聚合及分组
1.透视表(pivot_table)分析党派和职业
通过pivot_table
根据党派和职业对数据进行聚合,然后过滤掉总出资不足200万美元的数据
by_occupation = data.pivot_table('contb_receipt_amt',index='contbr_occupation',columns='party',aggfunc='sum')
over_2mm = by_occupation[by_occupation.sum(1)>2000000]
over_2mm
画出直方图
over_2mm.plot(kind = 'bar')
2.根据职业与雇主信息分组运算
根据职业分组,根据捐赠的金额排序输出最多的七个职业
def get_top_amounts(group,key,n=5):
#传入groupby分组后的对象,返回按照key字段汇总的排序前n的数据
totals = group.groupby(key)['contb_receipt_amt'].sum()
return totals.sort_values(ascending=False)[:n]
grouped = data_vs.groupby('cand_nm')
grouped.apply(get_top_amounts,'contbr_occupation',n=7)
cand_nm contbr_occupation
Obama, Barack RETIRED 25305316.38
ATTORNEY 14302461.84
NOT PROVIDED 13725187.32
HOMEMAKER 4248875.80
PHYSICIAN 3735124.94
CONSULTANT 2459912.71
PROFESSOR 2165071.08
Romney, Mitt NOT PROVIDED 11638509.84
RETIRED 11508473.59
HOMEMAKER 8147446.22
ATTORNEY 5372424.02
PRESIDENT 2491244.89
CEO 2324297.03
EXECUTIVE 2300947.03
Name: contb_receipt_amt, dtype: float64
同理可输出公司的捐赠排名
grouped.apply(get_top_amounts,'contbr_employer',n=10)
cand_nm contbr_employer
Obama, Barack RETIRED 22694558.85
SELF-EMPLOYED 18626807.16
NOT PROVIDED 13883494.03
NOT EMPLOYED 8586308.70
HOMEMAKER 2605408.54
STUDENT 318831.45
VOLUNTEER 257104.00
MICROSOFT 215585.36
SIDLEY AUSTIN LLP 168254.00
REFUSED 149516.07
Romney, Mitt NOT PROVIDED 12321731.24
RETIRED 11506225.71
HOMEMAKER 8147196.22
SELF-EMPLOYED 7414115.22
STUDENT 496490.94
CREDIT SUISSE 281150.00
MORGAN STANLEY 267266.00
GOLDMAN SACH & CO. 238250.00
BARCLAYS CAPITAL 162750.00
H.I.G. CAPITAL 139500.00
Name: contb_receipt_amt, dtype: float64
综上可以得出支持Obama和Romney的群体。
根据赞助人在不同捐助金额的多少进行分类比较
grouped_bins = data_vs.groupby(['cand_nm',labels])
grouped_bins.size().unstack(0)
每个阶层的捐赠总和
bucket_sums=grouped_bins['contb_receipt_amt'].sum().unstack(0)
bucket_sums
根据金额来画直方图
bucket_sums.plot(kind='bar')
用百分比来显示结果,更加明显
normed_sums = bucket_sums.div(bucket_sums.sum(axis = 1),axis=0)
normed_sums
normed_sums[:-2].plot(kind='bar',stacked=True)
按照赞助人姓名分组计数,计算重复赞助次数最多的前20人
data.groupby('contbr_nm')['contbr_nm'].count().sort_values(ascending=False)[:20]
contbr_nm
WILLIAMS, DEBBY 205
BERKE, DAVID MICHAEL 171
SEBAG, DAVID 161
SMITH, ERIK 145
FALLSGRAFF, TOBY 138
SKINNER, DONNA 136
CASPERSON, CAROLINA 132
HARRIS, CLAUDIA W. 132
ROSBERG, MARILYN 115
POTTS, LILLIE 114
DUDLEY, DEBBIE 111
HAUGHEY, NOEL ANTHONY 107
DFHDFH, DFHDFH 96
SHERWIN, GLEN R. 94
MITCHELL, CAITLIN 90
SMITH, CHARLES 88
KARIMIAN, AFSANEH 87
NURU, ISAAC 87
MASTERS, MARGERY 85
BIRMINGHAM, TOM 85
Name: contbr_nm, dtype: int64
四、时间处理
1.str转datetime
使用to_datetime方法解析多种不同的日期表示形式。对标准日期格式(如ISO8601)的解析非常快。我们也可以指定特定的日期解析格式,如pd.to_datetime(series,format='%Y%m%d')
data_vs['time'] = pd.to_datetime(data_vs['contb_receipt_dt'])
2.以时间作为索引
data_vs.set_index('time',inplace = True)
data_vs.head()
3.重采样和频度转换
vs_time = data_vs.groupby('cand_nm').resample('M')['cand_nm'].count()
vs_time.unstack(0)
fig, ax1=plt.subplots(figsize=(32,8))
vs_time.unstack(0).plot(kind='area',ax=ax1,alpha=0.6)
plt.show()
用面积图把11年4月-12年4月两位总统候选人接受的赞助笔数做个对比可以看出,越临近竞选,大家赞助的热情越高涨,奥巴马在各个时段都占据绝对的优势