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

小编们最近参加了数据城堡(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",得到本文的pdf版文件。

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

想了解更多? 那就赶紧来关注我们

原文发布于微信公众号 - 小小挖掘机(wAIsjwj)

原文发表时间:2017-02-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏人工智能LeadAI

讨厌算法的程序员 | 第四章 时间复杂度

增长量级 ? 函数的增长量级 上一篇算法分析基础中,我们分析了插入排序,知道了其最好情况下的运行时间为T(n) = an + b,最差情况下的运行时间为T(n...

30180
来自专栏顶级程序员

为什么Python是入行人工智能的首选语言?

在所有编程语言里,Python并不算萌新,从1991年发布第一个版本,至今已经快30年了。

24940
来自专栏牛客网

个人的前端面经,回馈社会

酷家乐(10-20k) 电话一面 三十五分钟 如何学习前端,看了什么书 谈实习经历 谈项目,问为什么用那么多插件,有没有想过自己写 position有几个属性 ...

38450
来自专栏有趣的Python和你

python数据分析之基情的择天记

names用于存入小说人物和出场次数;relationships保存人物关系的有向边,该字典的键为有向边的起点,值为一个字典edge,edge的键是有向边的终点...

10610
来自专栏码神联盟

语音识别 | Java 实现 AI 人工智能技术 - 语音识别功能

说到语音识别、语音翻译、图像识别、人脸识别等等,现在已经非常非常非常普及了,看过‘最强大脑’的朋友,也应该对‘小度’这个机器人有所了解,战胜国际顶尖的‘大脑’-...

2.5K60
来自专栏数据派THU

放弃“for循环”,教你用这种算法 !(附代码)

原文标题:Why you should forget ‘for-loop’ for data science code and embrace vectoriz...

27560
来自专栏程序人生

代码命名:僧敲月下门

忽一日於驴上吟得:‘鸟宿池中树,僧敲月下门。’初欲著‘推’字,或欲著‘敲’字,炼之未定,遂于驴上作‘推’字手势,又作‘敲’字手势。 - 《鉴戒录·贾忤旨》 两句...

31970
来自专栏平凡文摘

十年之后再看“面向对象”

12230
来自专栏HansBug's Lab

1015: [JSOI2008]星球大战starwar

1015: [JSOI2008]星球大战starwar Time Limit: 3 Sec  Memory Limit: 162 MB Submit: 3001...

29570
来自专栏WOLFRAM

一行代码论英雄—2017 Wolfram 语言“一行代码竞赛”结果

22960

扫码关注云+社区

领取腾讯云代金券