众所周知,美国大选是一个非常耗钱的事情。每个总统参加竞选时,都需要大量的经费。这些经费,几乎不会由候选人自己出,它们往往来自于政治献金。
美国法律要求,政治献金数据必须公开透明。于是,我们有了可以分析的数据。
需求:
- 加载数据
- 查看数据的基本信息
- 指定数据截取,将如下字段的数据进行提取,其他数据舍弃
- cand_nm:候选人姓名
- contbr_nm:捐赠人姓名
- contbr_st:捐赠人所在州
- contbr_employer:捐赠人所在公司
- contbr_occupation:捐赠人职业
- contb_receipt_amt:捐赠数额(美元)
- contb_receipt_dt:捐款的日期
- 对新数据进行总览,查看是否存在缺失数据
- 用统计学指标快速描述数值型属性的概要
- 空值处理。可能因为忘记填写或者保密等等原因,相关字段出现了空值,将其填充为 NOT PROVIDE
- 异常值处理。将捐款金额 <= 0 的数据删除
- 新建一列为各个候选人所在党派 party
- 查看 party 这一列中有哪些不同的元素
- 统计 party 列中各个元素出现次数
- 查看各个党派收到的政治献金总数 contb_receipt_amt
- 查看具体每天各个党派收到的政治献金总数 contb_receipt_amt
- 将表中日期格式转换为
'yyyy-mm-dd'
- 查看老兵(捐献者职业)DISABLED VETERAN 主要支持谁
在开始之前,导入各种需要的模块:
1 | import numpy as np |
加载数据。数据存储在文本文件中,直接用 read_csv 读取即可:
1 | df = pd.read_csv('data/usa_election.txt') |
前五条数据为:
1 | cmte_id cand_id cand_nm contbr_nm contbr_city contbr_st contbr_zip contbr_employer contbr_occupation contb_receipt_amt contb_receipt_dt receipt_desc memo_cd memo_text form_tp file_num |
查看数据的基本信息,调用 info 即可搞定:
1 | df.info() |
数据信息拿到。我们可以分析出来,总共有 536041 条数据,有些列是含有空值的:
1 | <class 'pandas.core.frame.DataFrame'> |
指定数据截取,将指定字段的数据进行提取,其他数据舍弃。注意提取数据的时候,内部是一个列表:
1 | data = df[['cand_nm', 'contbr_nm', 'contbr_st', 'contbr_employer', 'contbr_occupation', 'contb_receipt_amt', 'contb_receipt_dt']] |
截取后的前五条数据为:
1 | cand_nm contbr_nm contbr_st contbr_employer contbr_occupation contb_receipt_amt contb_receipt_dt |
对新数据进行总览,查看是否存在缺失数据
1 | data.info() |
除了捐助者和被捐助者,其余列都有空值存在:
1 | <class 'pandas.core.frame.DataFrame'> |
用统计学指标快速描述数值型属性的概要
1 | data.describe() |
因为只有献金金额是数值型数据,所以结果中只有现金金额这一列:
1 | contb_receipt_amt |
空值处理。可能因为忘记填写或者保密等等原因,相关字段出现了空值,将其填充为 NOT PROVIDE
1 | data.fillna('NOT PROVIDE', inplace=True) |
然后就可以看到,数据中已经没有空值了:
1 | <class 'pandas.core.frame.DataFrame'> |
异常值处理。将捐款金额 <= 0 的数据删除:
1 | data = data.loc[data['contb_receipt_amt'] > 0] |
从统计数据中可以看出,最小值也是大于 0 的:
1 | contb_receipt_amt |
新建一列为各个候选人所在党派 party,使用映射可以实现:
1 | dic = { |
数据中的前五行为:
1 | cand_nm contbr_nm contbr_st contbr_employer contbr_occupation contb_receipt_amt contb_receipt_dt party |
查看 party 这一列中有哪些不同的元素
1 | data['party'].unique() |
候选人来自的党派有:
1 | array(['Republican', 'Democrat', 'Reform', 'Libertarian'], dtype=object) |
统计 party 列中各个元素出现次数。一般情况下,只有能够接收到足够献金的党派胜选的概率才会更大:
1 | data['party'].value_counts() |
毫无疑问,民主和共和两党收到的献金是最多的:
1 | Democrat 289999 |
查看各个党派收到的政治献金总数 contb_receipt_amt
1 | data.groupby('party')['contb_receipt_amt'].sum() |
各党派收到献金的总数为:
1 | party |
查看具体每天各个党派收到的政治献金总数 contb_receipt_amt
1 | data.groupby(by = ['contb_receipt_dt', 'party'])['contb_receipt_amt'].sum() |
各党派每天收到的献金总数为:
1 | contb_receipt_dt party |
将表中日期格式转换为 'yyyy-mm-dd'
,可通过运算工具实现:
1 | months = {'JAN': 1, 'FEB': 2, 'MAR': 3, 'APR': 4, 'MAY': 5, 'JUN': 6, |
数据的前五行为:
1 | cand_nm contbr_nm contbr_st contbr_employer contbr_occupation contb_receipt_amt contb_receipt_dt party |
查看老兵(捐献者职业)DISABLED VETERAN 主要支持谁。
我们认为,哪个候选人接收到老兵的献金越多,老兵就越支持谁。
运算分两步,首先提取出老兵对应的行数据,然后根据候选人分组,运算得到老兵给每个候选人的献金:
1 | old_soldier = data.loc[data['contbr_occupation'] == 'DISABLED VETERAN'] |
我们可以看到有哪些老兵给哪位候选人献金:
1 | {'Cain, Herman': Int64Index([459440, 459447, 464508], dtype='int64'), |
对分组数据中的献金金额求和,即可得到每位候选人收到老兵献金的总额:
1 | old_soldier.groupby('cand_nm')['contb_receipt_amt'].sum() |
可见,奥巴马是最受老兵支持的:
1 | cand_nm |