python之Dataframe:多级表头和索引灵活的处理(一)

DataFrame俗称数据框,和一般的Excel表格没有多大区别,一般包含索引(行)和表头(列),在python中,由pandas包提供。

这是一个最简单的数据框类型,只包含一级索引和一级表头

如果你的python还没有这个包,请执行以下命令安装:

pip install pandas

这一节,我们要处理的主题是:多级表头和多级目录
先看看他们长什么样子:

表格1:包含二级表头和一级索引

表格二:包含二级索引和一级表头

在Excel里面看这些表格,还没什么特别的感觉,但是,今天我们要在python中来处理这样的表格,下面就开始吧!先说一下内容大概:

1. 如何构造出这样的表格
2. 对于这样的多级表格,如何修改,排序等常见操作

1. 如何构造多级表格

多级表格,常来自于实际的需要,许多时候,我们的数据并不是单一的表现形式,会有对比、计算、时间序列等因素。我先给出两个一级表格(也就是我们数据的原始形式)。

    日期  渠道  用户数 会话数 唯一身份浏览量
0   20180607    (Other) 3839    7324    15223
1   20180607    Direct  30060   35364   72330
2   20180607    Display 2   2   2
3   20180607    Organic Search  50636   57410   144043
4   20180607    Referral    2845    3370    8380
5   20180607    Social  1310    1564    3480
6   20180607    shareasale.com  214 238 568
    日期  渠道  用户数 会话数 唯一身份浏览量
0   20180531    (Other) 3756    6351    13825
1   20180531    Direct  33195   38812   78479
2   20180531    Display 2   2   2
3   20180531    Email   1   1   3
4   20180531    Organic Search  56003   64026   158187
5   20180531    Referral    3185    3769    9252
6   20180531    Social  3380    3690    7698
7   20180531    shareasale.com  241 268 658

Excel文件链接:https://pan.baidu.com/s/11xIBEm-jfj6o0Hz278Alvw 密码:b515
你需要将这个表格文件下载下来,使用pandas包的read_excel()函数读入。

这2个数据表格分别是2018年6月7号各个渠道的流量数据以及上周同期的数据,我们的目的是要做对比,把这2个表格的数据放到一起,方便对比查看。但我们用脑袋想一下,最方便对比的数据应该是什么样的呢?

前面我们已经给出了2个示例,分别是2级表头和2级索引,其实都起到了对比的作用。下面,我们就分别讲一下这2个表格是怎么做出来的。

1.1 我们先来构建多级表头,如下这样格式

表格1:包含二级表头和一级索引
  • 导入包,读入数据
import pandas as pd
from pandas import DataFrame

channel = pd.read_excel('处理多级表格-示例数据.xlsx',sheetname=0)
channel_last_week = pd.read_excel('处理多级表格-示例数据.xlsx', sheetname=1)

一般pandas包导入后会给个pd的别名。读入xlsx格式的数据使用函数pd.read_excel(),第一个参数是文件所在路径, 参数sheetname是指读入这个工作簿当中的哪个sheet,这里有2种写法:第一种是给出sheet的索引号(从左至右从0开始计数),第二种是给出sheet的具体名称,比如:

channel = pd.read_excel('处理多级表格-示例数据.xlsx',sheetname='20180607')
channel.set_index('渠道', inplace=True)
channel_last_week.set_index('渠道', inplace=True)

注:在pandas中,一般set_xxx类型的函数都会有一个参数inplace,代表是在原对象上修改,还是返回一个新的对象
这时候,我们的channel就变成了下面这样

image.png

我们来看一下它的index和columns

channel.index
Out[74]: Index(['(Other)', 'Direct', 'Display', 'Organic Search', 'Referral', 'Social', 'shareasale.com'], dtype='object', name='渠道')
channel.columns
Out[75]: Index(['日期', '用户数', '会话数', '唯一身份浏览量'], dtype='object')

如果细心的朋友一定会发现,index和columns的值其实都是属于同一个类: pandas.core.indexes.base.Index

type(channel.columns)
Out[76]: pandas.core.indexes.base.Index
type(channel.index)
Out[77]: pandas.core.indexes.base.Index
  • 现在来看这个日期,它里面的值应该是作为表头的,用来对比三个指标,所以,这里我们可以索性把它从columns中删除掉,到时候直接把它的值拿出来备用
yd,yd_la = '20180607','20180531'
channel.drop('日期', axis=1, inplace=True)
channel_last_week.drop('日期', axis=1, inplace=True)

第一行中两个变量间加逗号的写法,是一行同时实现2个及以上变量赋值的快捷写法,按顺序一一对应。
可能有人会说,我直接输入日期字符串会显得不够自动化和程序化,万一哪天传入的数据里面日期不是这两个呢?
其实你也可以使用如下的方法获取

yd,yd_la = channel.iloc[0,0],channel_last_week.iloc[0,0]

iloc是根据位置进行切片选择的,你也可以使用键名称和索引名称选择

yd,yd_la  = channel['日期']['Organic Search'],channel_last_week['日期']['Organic Search']

另外,删除列,除了使用drop外,还可以直接这样操作

del channel['日期']

这种写法我直接在原对象上删除,不像drop还可以选择返回删除后的新对象(不影响原对象)
drop除了可以删除列,还可以删除行,只需要设置axis=0(默认),输入索引值即可,比如

channel.drop('Direct') 

删除了索引值为Direct的行。
现在我们的channal对象是这样的了


image.png
  • 开始构造,最直观的做法就是把两个表中同一个指标的数据合并在一起,并且将日期作为底层表头,指标作为第二层表头
    DataFrame的合并函数有好几个:merge(基于column名称)、append、concat(基于index的值)...这里我们选择concat.
df_user = pd.concat([channel_last_week['用户数'], channel['用户数']],
                        keys=[yd_la, yd], axis=1).fillna(0)

先看一下结果:


image.png

请忽略小数(显示问题)。可以看到,左边是上周同期的,右边是6月7号的。
concat的参数:

  • 第一个list类型,元素是要合并的DataFrame;
  • keys起到的作用是,其值作为合并后新DataFrame的列名,axis=1的作用是横着合并(等于0的时候代表* 竖这合并,相当于拼接在下方);
  • 最后有个fillna函数,是因为如果有出现索引对不齐的情况,则会匹配出NA值(比如Email这个索引值就不是都有,匹配后20180607这列的值就为0)

  • 最后成型
    有了上面的合并经验,我们可以把上面的那个合并结果作为一个整体,然后对每一个columns指标都做同样的事情,最后合并起来,其keys的值就是原columns的值,如下所示:
df_session = pd.concat([channel_last_week['会话数'], channel['会话数']],
                        keys=[yd_la, yd], axis=1).fillna(0)
df_uv = pd.concat([channel_last_week['唯一身份浏览量'], channel['唯一身份浏览量']],
                           keys=[yd_la, yd], axis=1).fillna(0)
channel_together = pd.concat([df_user,df_session,df_uv],keys=['用户数', '会话数', '唯一身份浏览量'],axis=1).fillna(0)

最后来看我们的channel_together 长什么样

Out[119]: 
                    用户数               会话数           唯一身份浏览量          
               20180531 20180607 20180531 20180607 20180531  20180607
(Other)         3756     3839  6351     7324   13825    15223 
Direct          33195    30060  38812    35364  78479    72330 
Display         2        2.0      2        2      2        2     
Email           1        0.0      1        0      3        0     
Organic Search  56003    50636.0  64026    57410  158187   144043
Referral        3185     2845   3769     3370   9252     8380  
Social          3380     1310   3690     1564   7698     3480  
shareasale.com  241      214    268      238    658      568   

将其输出到Excel中就是目标中的那种格式啦!但是,你这个代码未免有点过长了,而且类似的代码比较多,现在,我们使用列表推导式,重新得到channel_together
发大招啦~~~

 channel_together = pd.concat([
        pd.concat([channel_last_week[column], channel[column]], keys=[yd_la, yd], axis=1)
        for column in ['用户数', '会话数', '唯一身份浏览量']], axis=1, keys=['用户数', '会话数', '唯一身份浏览量']).fillna(0)

看到没有,一句代码就解决!
未完待续~~~~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,340评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,762评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,329评论 0 329
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,678评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,583评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,995评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,493评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,145评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,293评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,250评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,267评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,973评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,556评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,648评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,873评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,257评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,809评论 2 339

推荐阅读更多精彩内容