1.数据载入和总览
首先导入要是用的包
#导入需要画图的包
import matplotlib.pyplot as plt
%matplotlib inline
#导入numpys,pandas的包
import numpy as np
import pandas as pd
from pandas import Series,DataFrame
1.1数据导入
%%time
contb1 = pd.read_csv('./usa_elect/contb_01.csv')
contb2 = pd.read_csv('./usa_elect/contb_02.csv')
contb3 = pd.read_csv('usa_elect/contb_03.csv')
注:%%time是jupyter notebook的魔法指令可以查看指令运行的时间,这里会显示加载文件时间
1.2数据合并
将上述三个文件合并起来,代码如下:
contb = pd.concat([contb1,contb2,contb3],axis=0)
#查看合并后的前五条信息
contb.head()
**注:concat函数是pandas里强大的合并方法,很多人不明白如何设置参数axis,这里一步到位,axis=0,可以理解为数据跨越行合并,axis=1可以理解为数据跨越列合并。是不是还不明白?没有关系看下面实例
1.3数据预览和基本统计分析
contb.shape
#数据总共有1001733条,总共有七列
(1001733,7)
2.数据清洗
从网络获取的数据一般都是杂乱无章的可以用英文‘RAW’来描述,并不能直接拿来使用,那可咋办,没关系pandas早已准备好了!
2.1缺失值处理
大量数据录入时难免会因一些原因造成某些值缺失,这些缺失值会以NaN来填充,但做数据分析时若不处理空值是很影响分析结果的,咱总不能让boss看到不大准确的分析结果吧,一般处理情况时删除缺失值或者填补一些默认值上去(例如平均值)。看我pandas如何打死你这小妖🐔。。。。。。。
首先查看哪些数据存在缺失
#获取contbr_employer的缺失值的实例
cond = contb['contbr_employer'].isnull()
contb[cond]
#获取contbr_employer这列为空值的数据
cond = contb['contbr_employer'].isnull()
contb[cond]
# 给没有提供contbr_employer的的数据填充‘NOT PROVIDE’
contb['contbr_employer'].fillna('NOT PROVIDE',inplace = True)
对contbr_occupation列和 contbr_st列也做同样的处理 处理后结果如下图:
2.2数据的转换
利用字典映射进行转换:党派分析
获取有哪些候选人
contb.cand_nm.unique()
结果为:array(['Bachmann, Michelle', 'Romney, Mitt', 'Obama, Barack', "Roemer, Charles E. 'Buddy' III", 'Pawlenty, Timothy', 'Johnson, Gary Earl', 'Paul, Ron', 'Santorum, Rick', 'Cain, Herman', 'Gingrich, Newt', 'McCotter, Thaddeus G', 'Huntsman, Jon', 'Perry, Rick'], dtype=object)
#通过搜索引擎等途径,获取到每个总统候选人的所属党派,建立字典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'}
%%time
# map中可以传递字典,100万数据,增加一列耗时133ms
contb['party'] = contb['cand_nm'].map(parties)
注:根据parties字典为每一条数据的候选人添加所属党派,既增加列‘party’
统计不同党派所支持的人数
contb['party'].value_counts()
统计各党派所获取捐赠的资金
contb.groupby('party')['contb_receipt_amt'].sum()
注:先调用groupby方法以党派进行分组(和sql里的gruop by 功能一样),然后调用sum统计各党派所得捐赠总金额
排序:按照职业汇总对赞助总金额进行排序
按照职位进行汇总,计算赞助总金额,展示前20项 但是机智的我发现不少职业是相同的,只不过是表达不一样而已,如C.E.O.与CEO,都是一个职业
因此可以定义一个字典把那些相似的职位统一一个名称
occupation = { 'INFORMATION REQUESTED PER BEST EFFORTS':'NOT PROVIDE', 'INFORMATION REQUESTED':'NOT PROVIDE', 'C.E.O.':'CEO', 'LAWYER':'ATTORNEY', 'SELF':'SELF-EMPLOYED', 'SELF EMPLOYED ':'SELF-EMPLOYED'}
#get(x,x)获取字典的值如果没有的话,以键填充
f = lambda x : occupation.get(x,x)
contb['contbr_occupation'] = contb['contbr_occupation'].map(f)
注:这里对于不熟悉python语法的会想这是什么@#@#@#¥#@!?
不要急听我慢慢到来 f = lambda x : occupation.get(x,x) 等价于
def occ_tra(x):
#判断参数x是否是字典occupation的键
#如果是occupation的键则返回对应的值(这里是统一的职位名称)如果没有的直接返回x
return occupation.get(x,x)
好了明白了咱接着往下说 contb['contbr_occupation'] = contb['contbr_occupation'].map(f) 统一数据里相似职位的名称,利用map映射对数据职位一一判断。
修改后获取数据如下:
2.3数据刷选
赞助金额筛选
由于某种原因有些数据捐赠的金额为负数,这显然是不合理的(咱总不能找奥巴马要钱是吧,好像总统工资也挺高的,我想找他要)
# 捐赠金额大于0
contb_=contb[contb['contb_receipt_amt']>0]
contb_
这里我的处理方法有两种
1.获取平均捐赠金额然后去填充这些负的捐赠金额
#获取平均值
ave = contb.contb_receipt_amt.mean()
#获取contb_receipt_amt<0的索引
index=contb[contb['contb_receipt_amt']<0].index
#将小于零的值赋予平均值
contb.iloc[index,5]=ave
2.删除负数值
contb_=contb[contb['contb_receipt_amt']>0]
contb_
查看各候选人获得的赞助总金额
cand_nm_amt=contb_.groupby(['cand_nm'])['contb_receipt_amt'].sum().sort_values(ascending=False)
cand_nm_amt.plot(kind='bar')
注:ascending=False表示以候选人获得总金额的降序排序, king='bar'表示以柱状图显示也可以以别的形式呈现可以使用shift+tab快捷键查看有哪些图形显示(是不是觉得以前用了假的画图工具。。。。。)
查询数据,例如查询候选人为Obama、Romney的子集数据
cond1 = contb_['cand_nm'] == 'Obama, Barack'
cond2 = contb_['cand_nm'] == 'Romney, Mitt'
cond = cond1|cond2
contb_vs = contb_[cond]
contb_vs
上面是pandas为我们提供的查询语句,是不是很简单,😄
和数据库查询语句结果一样'select * from table where cand_nm=='Obama, Barack' or cand_nm='Romney, Mitt'
虽然两者功能是一样的,但是pandas可要比数据库查询效率快的多了,不信的小伙伴可以用魔法指令%%time测试哈。
数据聚合与分组运算
3.1 透视表(pivot_table)分析党派和职业
按照党派、职业对赞助金额进行汇总,类似excel中的透视表操作,聚合函数为sum
ret = contb_.pivot_table('contb_receipt_amt',index='contbr_occupation',columns='party',aggfunc='sum',fill_value=0)
ret
增加total列
ret['total'] = ret['Democrat'] + ret['Republican']
根据不同职业捐赠总额进行降序排序(就是刚生成的total列)
ret.sort_values(by = 'total',ascending=False)
过滤掉赞助金额小于200W的数据,并使用柱状图呈现出来
cond = ret['total'] < 2000000
index = ret[cond].index
ret_big = ret.drop(labels=index)
#设置图形大小
plt.figure(figsize=(12,9))
ax = plt.subplot(1,1,1)
ret_big.plot(kind = 'bar',ax = ax)
3.2 分组级运算和转换
根据职业与雇主信息分组运算
由于职业和雇主的处理非常相似,我们定义函数get_top_amounts()对两个字段进行分析处理
def get_top_amounts(grouped,key,n):
# !!!先分组,grouped,然后继续再分
return grouped.groupby(key)['contb_receipt_amt'].sum().sort_values(ascending = False)[:n]
grouped = contb_.groupby('cand_nm')
grouped.apply(get_top_amounts,'contbr_occupation',7)
grouped = contb_vs.groupby('cand_nm')
grouped.apply(get_top_amounts,'contbr_occupation',7).unstack(level = 0)
从数据可以看出,Obama更受精英群体(律师、医生、咨询顾问)的欢迎,Romney则得到更多企业家或企业高管的支持,毕竟Obama是心里是有民众的嘛!
4.时间处理
4.1 str转datetime
先来查看各列的数据类型
contb_vs.dtypes
从上面我们可以发现时间的数据类型是object,这样的话如果时间作为画图坐标的显然是会出错的,那么有没有什么办法将object转换为时间类型呢?pandas已经为你想好了
contb_vs['contb_receipt_dt'] = pd.to_datetime(contb_vs['contb_receipt_dt'])
contb_vs.dtypes
好了转换后我先接下来要干啥呢?如下
4.2 以时间作为索引
contb_vs_time = contb_vs.set_index('contb_receipt_dt')
contb_vs_time.head()
然后呢?完了嘛?不不不我还没结束呢,
4.3重采样和频度转换
重采样(Resampling)指的是把时间序列的频度变为另一个频度的过程。把高频度的数据变为低频度叫做降采样(downsampling),resample会对数据进行分组,然后再调用聚合函数。这里我们把频率从每日转换为每月,属于高频转低频的降采样
# 行索引是时间,那么我们就可以实现重采样
vs_m = contb_vs_time.groupby(['cand_nm']).resample('M')['contb_receipt_amt'].sum().unstack(level = 0)
vs_m
5.各州支持率
首先依据州和候选人进行分组
state_vs = contb_vs.groupby(['cand_nm','contbr_st'])['contb_receipt_amt'].sum().unstack(level = 0)
state_vs
绘制图形显示:
plt.figure(figsize=(23,9))
ax = plt.subplot(1,1,1)
state_vs.plot(kind = 'bar',ax = ax)
根据结果显示what?美国怎么变成68个州了?难道又入侵了吗?很显然'AA','AB','AE','NOT AREA'等一些小国家厚着脸皮想要加入美国但是美国说你不行,什么时候人均GDP达到四万美金再来做我儿子吧!所以我们要将其剔除
state_vs_rate.drop(labels=['AA','AB','AE','NOT AREA'],inplace = True)
就是这么简单粗暴!inplace = True表示会修改原来的数据。
好了最后来看下个州的支持率吧!
如果你觉得这篇文章有收获就给我点个赞吧!
下期预告:使用Scipy处理图片