天池AI学习——pandas实践

Pandas实践

Pandas简介

在python中,pandas是一个强大的分析结构化数据工具集,它的使用基础是Numpy(提供高性能的矩阵运算);用于数据挖掘和数据分析,同时也提供数据清洗的功能。

在pandas中有两类非常重要的数据结构,即序列Series和数据框DataFrame。Series类似于numpy中的一维数组,除了通吃一维数组可用的函数或方法,而且可用索引标签的方式获取数据,还具有索引的自动对其功能。DataFrame类似于numpy中的二维数组,同样可以通过numpy数组的函数和方法,而且还具有其他灵活应用。

简单说一下pandas中数据的索引,例如一个序列,在不指定索引值的情况下,序列在输出时会自动生成一个从0开始的自增索引,或者我们也可以自定义一组索引值。从而,通过索引值或索引标签进行数据的获取。

需要注意的是,如果通过索引标签获取数据的话,末端标签对应的值是可以返回的!在一维数组中,就无法通过索引标签获取数据,这也是序列不同于一维数组的一个方面。

数据索引的另一个特点是自动对齐。当两个序列进行算术运算时,并不是像数组一样直接将两个序列对应位置的数相加,而是将两序列中相同索引的值相加。
关于pandas的一些数据处理方法可以参考:
https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12282042.0.0.13782042Bf3qat&postId=6068

在pandas实践中主要是对2012年美国总统竞选的赞助数据进行了分析。用到的数据可以参考这个百度云地址:https://pan.baidu.com/s/1r700VeA77UB2DbaM_untNQ

1.1数据的载入

利用pd.read_csv()函数将数据载入。由于单个数据量太大,所以可以将数据分成三个文件分别读入,再将读入的数据进行合并。

整个一起读入真的很慢,所以我手动将其分成了data1,data2,data3三个csv文件。。。

之后用pandas.read_csv(filepath,sep=’,’,header=‘infer’,names=None)函数来数据载入。
简单解释一下参数:
filepath:文本文件的路径
sep:分隔符,因为csv文件有的时候是用逗号分隔的数据,所以需要说明一下分隔符,避免读取的时候错误
header:指定行数用来作为列名。如果文件中没有列名,则默认为第一行的数据,否则设置为None,此时pandas会为其分配默认的列名
names:也可以用names传入列表指定列名

不过在这个实践中并没有用到那么多参数,只需要输入文本路径来读取即可。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

data_01=pd.read_csv('E:\pandas\data1.csv',low_memory=False)
data_02=pd.read_csv('E:\pandas\data2.csv',low_memory=False)
data_03=pd.read_csv('E:\pandas\data3.csv',low_memory=False)

1.2数据合并

这个很简单就是用pd.concat()函数把前三个列表放到一个列表中。

pandas.concat可以沿着一条轴将多个对象堆叠到一起。

该函数的语法是这样的pd.concat(objs, axis=0, join=‘outer’)。
其中objs是我们需要合并的对象,需要注意的是:当合并多个对象时需要将多个对象放到一个列表中。 axis=0默认按照0轴堆叠即按行合并,axis=1指合并列;concat函数可按照其他轴的逻辑关系进行合并,默认join=‘outer’,还有一个可取的值是’inner’。

data=pd.concat([data_01,data_02,data_03])

1.3 数据预览和基本统计分析

有几种方法可以在拿到数据时先大概看一下数据的情况。

一个是利用data.head()函数,或者data.tail()函数来查看数据的前5行或末尾5行。

比如我想查看数据集的前5行:

print(data.head())

输出结果是:
在这里插入图片描述
从前面自带的列索引号可以看出,我们用head()函数输出了数据表的前五行。

这里介绍一下每一列名称的含义

  • cand_nm:接收捐赠的候选人姓名
  • contbr_nm:捐赠人姓名
  • contbr_st:捐赠人所在州
  • contbr_employer:捐赠人所在公司
  • contbr_occupation:捐赠人的职业
  • contb_receipt_amt:捐赠数额(美元)
  • contb_receipt_dt:捐赠款到账的时间

还有其他列的一些数据,但是那些在这是pandas实践中并不是重要或者必要的数据,所以就不介绍了,其实从英文上也可以大概明白其中的意思。

除了查看列表的前5行和后5行数据外,还可以用data.info()查看数据的信息,包括字段的名称、非空的数量、字段的数据类型。

例如我们输入以下代码:

print(data.info())

输出结果如下:
在这里插入图片描述
可以看到,contbr_employer和contbr_occupation那有很多缺失数据。(其他上面介绍里没有提到的数据可以不考虑,因为不是主要的处理对象)

最后,还可以用data.describe()函数用统计学的方法快速对数据进行描述。

得到的效果是这样的:
在这里插入图片描述
它可以一下子得出一些基本的统计指标值。

2.1 缺失值的处理

上面用data.info()查看数据情况的时候已经发现了contbr_employer和contbr_occupation这两列里有不少缺失值。而在数据处理时,我们往往希望对缺失值进行填充,从而不妨碍对数据的进一步处理。

如果要对对所有的缺失数据进行填充,可以用下面的指令来实现:

data['contbr_employer'].fillna('NOT PROVIDED',inplace=True)
data['contbr_occupation'].fillna('NOT PROVIDED',inplace=True)

这样,就把contbr_employer和contbr_occupation列的缺失数据的都用‘NOT PROVIDED’填充了。

我们可以再输出一次data.info(),看一下缺失数据的填充效果。
在这里插入图片描述
整个列表一共有1001731行,因此可以看到contbr_employer和contbr_occupation两列已经没有缺失数据了。

2.2 数据转换

原始的列表中并没有给出受捐赠候选人所属的党派,而美国的大选一般就是民主党和共和党的党派之争,所以为了更好的分析美国大选的数据情况,我们应该将目光锁定在这两个党派的数据上。

为了在原始数据上添加一列“党派”信息,可以先构造一个字典,该字典中涵盖了所有候选人及其所属党派之间的对应关系。之后用映射的方式,将原始列表中的“党派”一列根据候选人名字填充满。

  • 查看所有候选人的名字
print('共有{}位候选人,分别是'.format(len(data['cand_nm'].unique())))
print(data['cand_nm'].unique())

data.unique()函数可以去掉序列中重复的部分

  • 构造一个候选人所属党派的字典
parties={'Bachmann,Michelle':'Republician',
         'Cain,Herman':'Republician',
         'Gingrich, Newt':'Republician',
         'Huntsman, Jon':'Republician',
         'Johnson, Gary Earl':'Republician',
         'McCotter, Thaddeus G':'Republician',
         'Obama, Barack':'Democrat',
         'Paul, Ron':'Republician',
         'Pawlenty, Timothy':'Republician',
         'Perry, Rick':'Republician',
         "Roemer, Charles E. 'Buddy' III":'Republician',
         'Romney, Mitt':'Republician',
         'Santorum, Rick':'Republician'
         }
  • 通过map映射函数,增加一列party来存储候选人的党派信息
data['party']=data['cand_nm'].map(parties)

map()函数可以映射函数也可以映射具有映射关系的字典。例如上边这句话的意思就是,找出data[‘cand_nm’]这一列中对应的候选人的名字在字典parties中对应的党派,将其填充到新增的party列。

以上我们就完成了新增党派列的操作,我们输出一下data.info()来看一下效果:
在这里插入图片描述
可以看到已经新增加了一列party,但是注意其后面还是有很多缺失值,这是因为我们只将民主党和共和党的数据填了进去,而对于其他党派我们并没有进行填充。

完成上述操作后,我们不妨来看一下民主党和共和党的受捐赠次数的比较。

将列表中的党派出现次数进行统计并排序:

print(data['party'].value_counts())

输出结果为:
在这里插入图片描述
可见民主党有更高的捐赠率。

其中用到的value_counts()函数可以对Series里的每个值进行计数,并按照计数大小从高往低排列。即对序列party中的每一个出现的党派进行计数。

但是只看捐赠次数而不考虑捐赠金额,是片面的。

于是我们可以看一下不同职业下总捐赠金额的情况。
但我们发现在数据表中,相同职业对象在捐赠时填写的职业写法往往有所出入。例如CEO有人写成了C.E.O.,以及律师写了lawyer和attorney。

因此我们可以先用get函数将所有相同含义的职业统一到一种写法,然后再进行职业捐赠总金额的统计。

  • 定义一个关于occupation的映射字典
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'}
  • 再定义一个捐赠人所属公司的映射字典
emp_mapping={
        'INFORMATION REQUESTED PER BEST EFFORTS':'NOT PROVIDED',
        'INFORMATION REQUESTED':'NOT PROVIDED',
        'SELF':'SELF-EMPLOYED',
        'SELF EMPLOYED':'SELF-EMPLOYED'}
  • 定义两个lambda函数
f=lambda x:occupation.get(x,x)
g=lambda x:emp_mapping.get(x,x)
  • 利用映射就该原来列表中的contbr_occupation和contbr_employer列
data.contbr_occupation=data.contbr_occupation.map(f)
data.contbr_employer=data.contbr_employer.map(g)

这里需要补充一下dict.get()的特点,它允许没有映射关系的对象也能通过。例如occupation.get(x,x)它会先将x代入字典中去比对关键字,如果x没有找到字典中一致的关键字,那么就默认输出原本的x。

  • 按职业分析捐赠金额总数并排序
print(data.groupby('contbr_occupation')['contb_recepit_amt'].sum().sort_values(ascending=False))

2.3 数据筛选

  • 赞助金额的筛选

因为在捐赠金额中会存在负数,也就是有退款的情况。所以我们首先要把这些数据去除。

data=data[data['contb_receipt_amt']>0]
  • 候选人的筛选
    因为两党之间的竞争会聚焦在少数候选人的身上,因此我们可以用下列程序将主要的竞争者筛选出来。
print(data.groupby('cand_nm')['contb_receipt_amt'].sum().sort_values(ascending=False))

先将其按照候选人名字聚合,然后计算不同候选人收到的捐赠额的总数并按从大到小的顺序排序。

最后得到的结果如下:
在这里插入图片描述
我们发现,Ombama和Romney是此次竞选的主要竞争对象。
这样我们可以将Ombama和Romney的数据单独拎出来造一个子集,对该子集进行分析可以对数据的分析更有针对性。

data_vs=data[data['cand_nm'].isin(['Ombama,Barack','Romney,Mitt'])].copy()

2.4 面元化数据

我们可以用cut函数将出资金额离散化到多个区间即面元内:

bins=np.array([1,10,100,1000,10000,100000,1000000,10000000])
labels=np.cut(data['contb_receipt_amt'],bins)
print(labels)

在这里插入图片描述
contb_receipt_amt这一列的金额都被划分到了后面的区间内。
利用cut函数是一种将连续数据离散化的很好的方法。

3.1 用透视表分析党派和职业

在之前我们已经将每个受捐赠人所属的党派和捐赠人的职业搞清楚了,现在我们可以分析一下每个不同职业对共和党和民主党的支持情况。

这里用到了透视表操作。透视表是一种可以对数据动态排布并且分类汇总的表格格式。或许大多数人都在Excel使用过数据透视表,也体会到它的强大功能,而在pandas中它被称作pivot_table。它不仅灵活性高,而且脉络清晰、容易理解数据,操作性强。具体的我就不在这里多说了。

直接看代码:

by_occupation=data.pivot_table('contb_receipt_amt',index='contbr_occupation',columns='party',aggfunc='sum')
print(by_occupation)

得到的结果:
在这里插入图片描述
我只截取了前几行的数据。

当然,这并不是最重要的,我们希望过滤掉捐赠数额小于200w的数据。

over_2mm=by_occupation[by_occupation.sum(1)>2000000]#过滤
over_2mm.plot(kind='bar')#画柱状图

在这里插入图片描述
这样每个职业在这次竞选中的捐赠情况就很明显了。

3.2 分组级运算和转换

在这个部分我们想有针对性的了解一下,支持Ombama和Romney的人群分别又怎么样的职业特点。
我们使用apply函数对数据表中的每一列进行函数运算。这个过程主要分了三个部分:写一个将捐赠最多的前几个职业输出的函数,对data_vs数据按照名字进行聚合,对聚合后的数据应用编好的函数提取出捐赠最多的前几个职业。

  • 代码
def mount_top(group,key,n=5):
    group=group.groupby(key)['contb_receipt_amt'].sum().sort_values(ascending=False)
    return (group[:n])
grouped=data_vs.groupby('cand_nm')
top_occupation=grouped.apply(mount_top,'contbr_occupation',n=7)

得到的结果是:
在这里插入图片描述
可见Obama更受精英人士的支持,例如:咨询顾问、教授、医生的支持;而Romney则更受企业高层例如CEO、经理的支持。
将上面的key字段换成’contbr_employer’可以观察两位候选人更受哪些企业的支持。

除了上述操作,我们还想知道两位竞选人收到的赞助金额的占比是如何的?
我们之前已经用cut函数将赞助金额进行了离散化,那么我们可以直接画出两位竞选人在不同金额区间内得到的金额赞助情况。

grouped_bins=data_vs.groupby(['cand_nm',labels])
bucket_sums=grouped_bins['contb_receipt_amt'].sum().unstack(0)
print(bucket_sums)

在这里插入图片描述
这里我想注明一点,之前我在用上面这个代码时,我觉得groupby后面的参数一定得是原数据表中的列名,但是labels并不是,它只是和‘contb_receipt_amt’有对应关系的序列而已,且它的长度与data_vs的一致,所以它也可以用来groupby。

很明显,只是用数表的形式来看这些数据还不够清晰。所以我们可以把它画成柱状图来看一下。

bucekt_sums.plot(kind='bar')

在这里插入图片描述
这样两个竞争者在资金方面的对比就很明显了。

但是这样的对比还不够突出,这时候我们可以尝试一下百分比的堆叠图,这样可以更加突出Obama和Romney受捐赠金额的对比情况。

normed_sums=bucket_sums.div(bucket_sums.sum(1),axis=0)
normed_sums[:-2].plot(kind='bar',stacked=True)

用DataFrame.div函数计算每一阶段金额中Obama和Romney的占比,并以堆叠图的形式输出。

在这里插入图片描述
现在很明显可以看出,Obama在小额赞助上的金额具有很大的优势。

4.1 datetime处理时间

我们可以使用to_datetime方法解析多种不同的日期表现形式,因为在时间的记录上其实有很多格式和方式。对标准日期格式(如ISO8601)的解析非常快。我们也可以指定特定的日期解析格式,如pd.to_datetime(Series,format=’%Y%m%d’)

因此我们可以用下列代码将’contb_receipt_dt’列的时间转换为标准时间格式:

data_vs['time']=pd.to_datetime(data_vs['contb_receipt_dt'])

最后我们在data_vs中新增了一列time来存放标准后的时间。
在这里插入图片描述

4.2 以时间为索引

上面虽然我们新增加了一列time,但是我们往往希望能用将时间作为索引。因此,就可以用set_index函数来实现。

data_vs.set_index('time',inplace=True)
print(data_vs.head())

在这里插入图片描述
此时time列已经被设置为索引了。

4.3 重采样和频度转换

重采样指的是把时间序列的频度变为另一个频度的过程。我们把高频度数据变为低频度叫做降采样,重采样会对数据进行分组,然后再调用聚合函数。

这里我们把频率从每日转换为每月,属于高频转低频的降采样。

vs_time=data_vs.groupby('cand_nm').resample('M')['cand_nm'].count()

在这里插入图片描述
这里面统计了每个月两位竞选者受捐赠的次数。

最后,我们用面积图吧11年4月-12年4月两位总统候选人接收赞助笔数做个对比。

fig1,ax1=plt.subplots(figsize=(32,8))
vs_time.unstack(0).plot(kind='area',ax=ax1,alpha=0.6)
plt.show()

最后结果如下,可以看出越到竞选后期,Obama的受赞助率越高。
在这里插入图片描述
这样整个简单的数据分析就结束了。
其实里面的分析有的时候很乱,所以需要反复的理一下。
但是里面用到了很多非常实用的数据分析方法,pandas的很多功能都用到了,所以是个很不错的实践。

主要参考:https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12282042.0.0.13782042tFQhoS&postId=10585

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值