查看原文
其他

数据城堡参赛代码实战篇(一)---手把手教你使用pandas

文文 Python爱好者社区 2019-04-07

作者:文文

个人公众号:小小挖掘机(ID:wAIsjwj)


最近参加了数据城堡(http://www.pkbigdata.com/)举办的“大学生助学金精准资助预测”比赛,分组第19名的成绩进入了复赛,很激动有木有!本篇,文文将带你一起分析如何用pandas来对官方给出的数据进行处理和分析。

1 引言

在进入正题之前呢,我们先来了解两件事情:pandas和官方数据。

1.1Pandas

首先,什么是pandas,相信很多数据挖掘爱好者对此已经非常熟悉,那么你可以直接跳过此处。Pandas 是python的一个数据分析包,提供了大量能使我们快速便捷地处理数据的函数和方法。在代码中使用pandas,首先需要导入:

import pandas as pd

它主要的数据结构有如下两种:


Series


Series类似于一维数组对象,它由一组数据以及一组与之相关的数据标签组成,简单的Series可以按下面的方式进行创建:

obj=pd.Series([4,7,5,3])

输出如下:

0 4 1 7 2 5 3 3

其中,第一列是Series的索引列(index),第二列是数值列(values)。

DataFrame

DataFrame是一个表格型的数据结构,既有行索引又有列索引。行索引称为index,标示每一行数据,列索引称为columns,标示每一列数据。可以简单理解为一个数据表,列索引为数据表中除主键外的一个个字段,行索引相当于数据表中每一条数据的主键值。通过dict来创建DataFrame可以按如下的方式:

data={ 'state':['Ohio','Ohio','Ohio','Nevada','Nevada'], 'year':[2001,2001,2002,2001,2002], 'pop':[1.5,1.7,3.6,2.4,2.9] } frame=pd.DataFrame(data)

如果不指定索引,结果中会自动加入行索引,而dict中的key则将作为列索引,输出如下:

   pop    state    year 0   1.5     Ohio    2000 1   1.7     Ohio    2001 2   3.6     Ohio    2002 3   2.4     Neva    2001 4   2.9     Neva    2002

1.2 官方数据


这里文文想偷一下懒,所以直接把网上的数据介绍粘过来啦,嘻嘻😁。(需要数据的同学可以在后台回复“数据代码哟)

数据总体描述

数据分为两组,分别是训练集和测试集,每一组都包含大约1万名学生的信息纪录:

图书借阅数据borrow_train.txt和borrow_test.txt、

一卡通数据card_train.txt和card_test.txt、

寝室门禁数据dorm_train.txt和dorm_test.txt、

图书馆门禁数据library_train.txt和library_test.txt、

学生成绩数据score_train.txt和score_test.txt

助学金获奖数据subsidy_train.txt和subsidy_test.txt

数据详细描述

(1)图书借阅数据


    字段描述和示例如下:

    学生id,借阅日期,图书名称,图书编号

    9708,2014/2/25,"我的英语日记/ (韩)南银英著  (韩)卢炫廷插图","H315 502"

    6956,2013/10/27,"解读联想思维: 联想教父柳传志","K825.38=76 547"

    9076,2014/3/28,"公司法 gong si fa = = Corporation law / 范健, 王建文著 eng"


(2)一卡通数据


    字段描述和示例如下:

    学生id,消费类别,消费地点,消费方式,消费时间,消费金额,剩余金额

    1006,"POS消费","地点551","淋浴","2013/09/01 00:00:32","0.5","124.9"

    1406,"POS消费","地点78","其他","2013/09/01 00:00:40","0.6","373.82"

    13554,"POS消费","地点6","淋浴","2013/09/01 00:00:57","0.5","522.37"


(3)寝室门禁数据


    字段描述和示例如下:

    学生id,具体时间,进出方向(0进寝室,1出寝室)

    13126,"2014/01/21 03:31:11","1"

    9228,"2014/01/21 10:28:23","0"


(4)图书馆门禁数据


    图书馆的开放时间为早上7点到晚上22点,门禁编号数据在2014/02/23之前只有“编号”信息,之后引入了“进门、出门”信息,还有些异常信息为null,请参赛者自行处理。

    字段描述和示例如下:

    学生id,门禁编号,具体时间

    3684,"5","2013/09/01 08:42:50"

    7434,"5","2013/09/01 08:50:08"

    8000,"进门2","2014/03/31 18:20:31"

    5332,"小门","2014/04/03 20:11:06"

    7397,"出门4","2014/09/04 16:50:51"


(5)学生成绩数据

    注:成绩排名的计算方式是将所有成绩按学分加权求和,然后除以学分总和,再按照学生所在学院排序。

    学生id,学院编号,成绩排名

    0,9,1

    1,9,2

    8,6,1565

    9,6,1570


(6)助学金数据

    字段描述和示例如下:

    学生id,助学金金额(分隔符为半角逗号)

    10,0

    22,1000

    28,1000

    64,1500

    650,2000

2 数据处理实战

官方给出了示例代码,对一卡通数据以及学生成绩进行了处理(需要官方代码的同学可以在后台回复“数据代码”),获得了一个学生在学院的成绩排名、消费总金额,平均消费金额以及单次最大消费金额等等特征,这些文文就不一一赘述其处理过程啦,有兴趣的同学可以阅读示例代码进行学习。这里,文文想通过pandas介绍一下我们是如何对数据进行处理,得到我们想要的特征的。

2.1 恩格尔系数计算

既然官方的一卡通数据给出了消费类别,有食品、超市、淋浴等等,我们很容易想到的是恩格尔系数,它表示食品支出占一个人总支出的比重。那么下面文文将根据官方给出的数据,带你一步步分析计算每个人的恩格尔系数。


1)读取数据


我们利用pandas的read_csv方法将数据读入到DataFrame中:

#没有columns数据,header属性设置为None card_df=pd.read_csv('card_train.txt',header=None)

由于官方没有给定colunms,我们对columns属性进行赋值:

card_df.columns = ['id','consume','where','how','time','amount','remainder']

我们可以先来看一下前10行的数据,使用head()方法

print (card_df.head(10))

输出结果如下:

id   consume  where   how     time     amount remainder 1006   POS消费  地点551  淋浴  2013/09/01   0.50  124.90 1006   POS消费  地点551  淋浴  2013/09/01   0.50  124.90 1968   POS消费  地点159  淋浴  2013/09/01   0.10  200.14 1968   POS消费  地点159  淋浴  2013/09/01   0.10  200.14 1406   POS消费  地点660  开水  2013/09/01   0.01  374.42 1406   POS消费  地点660  开水  2013/09/01   0.01  374.42 1406   POS消费   地点78  其他  2013/09/01   0.60  373.82 1406   POS消费   地点78  其他  2013/09/01   0.60  373.82 13554  POS消费    地点6  淋浴  2013/09/01   0.50  522.37 13554  POS消费    地点6  淋浴  2013/09/01   0.50  522.37

天呐,这有点太乱了吧,没关系,小编带你一步步简化数据!


2)数据汇总


想要计算恩格尔系数,需要知道每个人的食品支出以及消费总支出,即我们想要看到的结果是这样子的:

id 图书馆  食堂  超市 开水 教务处 文印中心 校医院..... 01  0.0  100.0 20.0 5.0   3.0   10.0   100.0 02  0.0  100.0 20.0 5.0   3.0   10.0   100.0 02  0.0  100.0 20.0 5.0   3.0   10.0   100.0

下面文文将用两种方法带你得到这样的汇总数据


使用groupby()方法


groupby,顾名思义,就是对数据进行分组的意思。可以看出我们首先需要按照学生的id进行分组,再按照消费类别进行分组,对分组后的数据,我们还需要一个加总的方法来得到每个学生在每个类别下的总支出。groupby的使用如下:

#首先,使用groupby,指定首先按照id进行分组,再按照how列进行分组, #对于分#组后的数据,我们取amount列,并进行加总处理 card_group=card_df.groupby(['id','how'])['amount'].sum()

得到的结果如下:

id     how 0      图书馆       84.40       开水       429.58       文印中心       0.30       校车       417.49       淋浴        12.30       超市       839.68       食堂       647.81 1      图书馆      324.20       开水       265.97       教务处       29.30       文印中心      96.40       校车       119.40       洗衣房       25.02       淋浴        22.50       超市       514.30       食堂      1540.60

就快要成功啦,但是离我们的目标还差一点,我们需要将以how命名的行标签转换成列标签,就可以得到我们想要的结果啦。想要行标签转换成列标签,我们可以使用pandas提供的unstack方法,具体如下:

card_group=card_group.unstack('how')

unstack方法将我们指定的行标签转换成列标签,我们可以看一下此时的输出结果:

Name: amount, dtype: float64 how   其他  图书馆    开水    教务处 文印中心  校医院   校车    洗衣房   淋浴    超市      食堂 id                                                                       0     NaN   84.40   429.58   NaN    0.3     NaN   417.49    NaN   12.30  839.68   647.81 1     NaN  324.20   265.97  29.3   96.4     NaN   119.40   25.02   22.50  514.30  1540.60 8     NaN  425.90  2440.94   NaN    2.6     NaN  2211.45   4.50   39.83    0.00   387.15

得到上面的结果,我们马上就要大功告成啦,但是我们发现结果中有NAN的数据,表明该学生没有该类别的消费记录。我们可以用fillna方法将其转换:

#用0替换NaN值,同时直接覆盖原DataFrame card_group.fillna(0,inplace=True)

再次看一下我们的输出,大功告成!

Name: amount, dtype: float64 how   其他  图书馆    开水    教务处 文印中心  校医院   校车    洗衣房   淋浴    超市      食堂 id 0     0.0   84.40   429.58   0.0    0.3     0.0   417.49    0.0   12.30  839.68   647.81 1     0.0  324.20   265.97  29.3   96.4     0.0   119.40   25.02   22.50  514.30  1540.60 8     0.0  425.90  2440.94   0.0    2.6     0.0  2211.45   4.50   39.83    0.00   387.15

使用pivot_table()方法


如果你是一名熟练的excel爱好者,很容易想到的是使用数据透视表来实现我们所要的结果。没错,pandas也提供了数据透视表的功能,相对于使用groupby来说,数据透视表更加的便捷快速,代码如下:

#第一个参数指定我们需要计算的列,第二个参数指定行标签,第三个参数代表列标签, #aggfunc参数指定对需要计算的列的计算方法,此处用sum方法进行汇总,如果是计数,使用len方法 card_group=card_df.pivot_table('amount',index=['id'],columns=['how'],aggfunc=sum)

结果如下:

how   其他  图书馆    开水    教务处 文印中心  校医院   校车    洗衣房   淋浴    超市      食堂 id                                                                       0     NaN   84.40   429.58   NaN    0.3     NaN   417.49    NaN   12.30  839.68   647.81 1     NaN  324.20   265.97  29.3   96.4     NaN   119.40   25.02   22.50  514.30  1540.60 8     NaN  425.90  2440.94   NaN    2.6     NaN  2211.45   4.50   39.83    0.00   387.15

再对上面的结果中的NaN进行替换,即可得到我们想要的结果,此处不再赘述。


3)计算恩格尔系数


对于上一节中的得到的汇总数据,我们首先需要计算学生的总消费金额,具体如下:

#使用sum()方法 #指定axis=1,表示对每一行的数据进行加总,默认为0 #将计算的结果赋值到‘总计’列 card_group['总计']=card_group.sum(axis=1,skipna=False)

得到了汇总结果,接下来就好处理了,仅需要用食堂消费除以总消费即可得到每一个人的恩格尔系数:

card_group['恩格尔1']=card_group['食堂']/card_group['总计']

我们来看一下结果:

print card_group[['食堂','总计','恩格尔1']]

输出如下:

how      食堂     总计      恩格尔1 id                               0       647.81  2431.56  0.266417 1      1540.60  2937.69  0.524426 8       387.15  5522.37  0.070106 9      1899.60  7402.91  0.256602 10      944.84  2907.44  0.324973 11      333.40  2670.80  0.124832 19      513.31  1513.06  0.339253

最后我们使用to_csv方法将数据写入到csv文件中即可。

card_group.to_csv('card_train.csv',encoding='gbk')

至此,我们计算恩格尔系数的目标大功告成!很激动有木有!


3 总结


本篇,文文带你详细介绍了在参与此次比赛过程中使用pandas计算恩格尔系数的主要过程,重点介绍了groupby()和pivot_table()方法,相信大家已经初步领略到了pandas的神奇之处,更多关于pandas的使用方法,可以参考《使用python进行数据分析》一书。


文文也是入门阶段,如果文中有写的不合适或者错误的地方,欢迎大家批评指正。如果代码格式显示出现问题,欢迎您在后台回复"数据代码",得到本文的pdf版文件。


处理完数据,如何得到最终可以提交的结果呢?下期,文文将带你初步探索sklearn机器学习库的秘密,敬请期待!

Python爱好者社区历史文章大合集

Python爱好者社区历史文章列表(每周append更新一次)

福利:文末扫码立刻关注公众号,“Python爱好者社区”,开始学习Python课程:

关注后在公众号内回复“课程”即可获取:

小编的Python入门视频课程!!!

崔老师爬虫实战案例免费学习视频。

丘老师数据科学入门指导免费学习视频。

陈老师数据分析报告制作免费学习视频。

玩转大数据分析!Spark2.X+Python 精华实战课程免费学习视频。

丘老师Python网络爬虫实战免费学习视频。


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存