使用Python轻松应对一维表与二维表相互转换

数据分析时,同事经常给你一份二维表,是不是分分钟有想哭的冲动,一大堆的东西在一块,怎么透视?想要做进一步分析,也是特别麻烦。今天给你一种方便的方法。

一、入门版

先来看看可能要处理的文件是什么样的?


看看,别提多闹心了。当然我们不可能一开始就处理这么复杂的样式。先来个简单的验证一下。



如上这样一个二维数据,怎么变成一维数据呢?

excel中可以这样操作

  1. 选择数据透视表,快捷键alt+d+p,这里是用wps的演示的,用office是一样的效果


  2. 选择多重合并计算区域


  3. 创建单面字段


  4. 选择数据区域


  5. 添加数据区域


  6. 点击完成,默认新工作表确定


  7. 这样一个数据透视表就出现了



    到这时,读者可能想,还是没有变成一维表呀,这不依然是二维表。别急,还有下面的关键步骤。

  8. 在透视表的区域里去除行和列的数据,只保留值的区域


    改变前
改变后

这是我们的数据透视表变成了这样:


  1. 双击数值,我们这里就是这个6762


这时就进入了这样一个界面,相信细心的朋友一定能发现这里正好就是我们要的二维数据了,复制整个内容,更改一下列名。

让我们头痛的二维表就这样变成了一维表。

二、进阶版

完成了这样一个简单的验证,我们再来考虑一下我们开头提到的复杂样式?这个该怎么处理呢?是不是也可以用这种方法解决呢?

先试一试

好像没那么管用了,我们希望的是二级区域,业务员,类型这些也能像一级大区这样展开,可是这里却混在了一起。这可怎么办呢?

Pandas来救场

熟悉python的应该知道,python经常被说成是数据分析的好工具,但是其实python能进入数据分析领域,pandas才是其中最大的功臣,pandas和numpy成为python数据分析最大的法宝。这里我们就要用到pandas的一个很方便的功能。

  1. 引入相关包
# 引入相关包
import pandas as pd
import numpy as np
  1. 读入文件
# 读入文件
file = r"E:\销售数据报表项目\医美专题\2dims.xlsx"
df = pd.read_excel(file)
df.head()

数据输出:

    一级大区    二级区域    业务员 型号  1月  2月  3月  4月  5月  6月  7月  8月  9月  10月 11月 12月
0   南区  浙南区域    name1   type1   222.392385  110.46942   207.566226  208.341450  234.989775  244.680075  239.834925  249.525225  205.918875  276.17355   296.52318   290.709
1   南区  浙南区域    name1   type2   52.166115   25.91258    48.688374   48.870217   55.121058   57.394092   56.257575   58.530608   48.301958   64.78145    69.55482    68.191
2   南区  浙南区域    name2   type1   866.394630  430.36596   808.634988  811.655100  915.471450  953.222850  934.347150  972.098550  802.217250  1075.91490  1155.19284  1132.542
3   南区  浙南区域    name2   type2   203.228370  100.95004   189.679812  190.388233  214.740217  223.595483  219.167850  228.023117  188.174417  252.37510   270.97116   265.658
4   南区  浙南区域    name3   type1   1280.382795 636.00714   1195.023942 1199.487150 1352.909925 1408.700025 1380.804975 1436.595075 1185.539625 1590.01785  1707.17706  1673.703

可以看到,和我们在excel里看到的内容是一致的。
下面我们就要开始变换处理了。

  1. 变换处理
# 变换处理
df1 = df.set_index(['一级大区','二级区域','业务员','型号'])
df2 = df1.stack()
df3 = df2.reset_index()
df3.columns = ['primary_area', 'sub_area', 'sales_man',
               'product_specifications', 'month', 'target']
df3

数据输出:

    primary_area    sub_area    sales_man   product_specifications  month   target
0   南区  浙南区域    name1   type1   1月  222.392385
1   南区  浙南区域    name1   type1   2月  110.469420
2   南区  浙南区域    name1   type1   3月  207.566226
3   南区  浙南区域    name1   type1   4月  208.341450
4   南区  浙南区域    name1   type1   5月  234.989775
5   南区  浙南区域    name1   type1   6月  244.680075
6   南区  浙南区域    name1   type1   7月  239.834925
7   南区  浙南区域    name1   type1   8月  249.525225
8   南区  浙南区域    name1   type1   9月  205.918875
9   南区  浙南区域    name1   type1   10月 276.173550
10  南区  浙南区域    name1   type1   11月 296.523180
11  南区  浙南区域    name1   type1   12月 290.709000
12  南区  浙南区域    name1   type2   1月  52.166115
...
3405    北区  山东大区    name140 type2   10月 127.680000
3406    北区  山东大区    name140 type2   11月 137.088000
3407    北区  山东大区    name140 type2   12月 134.400000
3408 rows × 6 columns

可以看到,二维表已经变成了我们想要的一维表了。
这中间到底发生了什么魔法?
我们来解释下刚刚的代码:

# 变换处理开始
# 首先把数据df设置成多项索引,就像下面这样
df1 = df.set_index(['一级大区','二级区域','业务员','型号'])
# 然后把二维表格变成堆叠样式
df2 = df1.stack()
# 再把堆叠样式的数据重建索引
df3 = df2.reset_index()
# 我们把原来一行的内容转变成一列了,系统当然不知道应该叫什么,
# 所以我们这里要给新出现的列命名,这里为了方便后面分析使用,
# 直接给所有列重命名成英文
df3.columns = ['primary_area', 'sub_area', 'sales_man',
               'product_specifications', 'month', 'target']
# 那么为什么要生成df1,2,3呢? 这是为了覆盖原数据,防止我们误操作了没法复原

再来看看,每次变更后的数据是怎么样的:

# 设置多项索引后
In: df1
Out: 
                1月  2月  3月  4月  5月  6月  7月  8月  9月  10月 11月 12月
一级大区    二级区域    业务员 型号                                              
南区  浙南区域    name1   type1   222.392385  110.469420  207.566226  208.341450  234.989775  244.680075  239.834925  249.525225  205.918875  276.17355   296.52318   290.709
type2   52.166115   25.912580   48.688374   48.870217   55.121058   57.394092   56.257575   58.530608   48.301958   64.78145    69.55482    68.191
name2   type1   866.394630  430.365960  808.634988  811.655100  915.471450  953.222850  934.347150  972.098550  802.217250  1075.91490  1155.19284  1132.542
type2   203.228370  100.950040  189.679812  190.388233  214.740217  223.595483  219.167850  228.023117  188.174417  252.37510   270.97116   265.658
name3   type1   1280.382795 636.007140  1195.023942 1199.487150 1352.909925 1408.700025 1380.804975 1436.595075 1185.539625 1590.01785  1707.17706  1673.703
type2   300.336705  149.186860  280.314258  281.361183  317.349242  330.435808  323.892525  336.979092  278.089542  372.96715   400.44894   392.597
name4   type1   891.738315  442.954980  832.289094  835.397550  942.250725  981.106425  961.678575  1000.534275 825.683625  1107.38745  1188.98442  1165.671
type2   209.173185  103.903020  195.228306  195.957450  221.021775  230.136075  225.578925  234.693225  193.678875  259.75755   278.89758   273.429
浙北区域    name5   type1   644.436000  320.112000  601.473600  603.720000  680.940000  709.020000  694.980000  723.060000  596.700000  800.28000   859.24800   842.400
type2   151.164000  75.088000   141.086400  141.613333  159.726667  166.313333  163.020000  169.606667  139.966667  187.72000   201.55200   197.600
name6   type1   619.650000  307.800000  578.340000  580.500000  654.750000  681.750000  668.250000  695.250000  573.750000  769.50000   826.20000   810.000
# 改成堆叠样式后
In:df2
Out:
一级大区  二级区域  业务员      型号        
南区    浙南区域  name1    type1  1月     222.392385
                            2月     110.469420
                            3月     207.566226
                            4月     208.341450
                            5月     234.989775
                            6月     244.680075
                            7月     239.834925
                            8月     249.525225
                            9月     205.918875
                            10月    276.173550
                            11月    296.523180
                            12月    290.709000
                     type2  1月      52.166115
                            2月      25.912580
                            3月      48.688374
                            4月      48.870217
                            5月      55.121058
                            6月      57.394092
                            7月      56.257575
                            8月      58.530608
                            9月      48.301958
                            10月     64.781450
                            11月     69.554820
                            12月     68.191000
            name2    type1  1月     866.394630
                            2月     430.365960

有点像是大括号括起来的效果。不过这里可以看到月份和销售额是没有列名的。

# 这里为了演示,又重新建了一个df, 
# 因为前面df3已经重命名列名了
In: df4 = df2.reset_index()
    df4
Out:
    一级大区    二级区域    业务员 型号  level_4 0
0   南区  浙南区域    name1   type1   1月  222.392385
1   南区  浙南区域    name1   type1   2月  110.469420
2   南区  浙南区域    name1   type1   3月  207.566226
3   南区  浙南区域    name1   type1   4月  208.341450
4   南区  浙南区域    name1   type1   5月  234.989775
5   南区  浙南区域    name1   type1   6月  244.680075
6   南区  浙南区域    name1   type1   7月  239.834925
7   南区  浙南区域    name1   type1   8月  249.525225
8   南区  浙南区域    name1   type1   9月  205.918875
9   南区  浙南区域    name1   type1   10月 276.173550
10  南区  浙南区域    name1   type1   11月 296.523180
11  南区  浙南区域    name1   type1   12月 290.709000

可以看到,前面的一级大区,二级区域这些内容被填充上内容了。但是月份和销售额还是没有列名。

In: df4.columns = ['primary_area', 'sub_area', 'sales_man',
               'product_specifications', 'month', 'target']
    df4
Out:
    primary_area    sub_area    sales_man   product_specifications  month   target
0   南区  浙南区域    name1   type1   1月  222.392385
1   南区  浙南区域    name1   type1   2月  110.469420
2   南区  浙南区域    name1   type1   3月  207.566226
3   南区  浙南区域    name1   type1   4月  208.341450

这样就完成了一个多项索引的二维表到一维表的转换。可以看到使用pandas方便快捷,最关键的是能处理excel不太方便的地方。

后记

到这里,今天的内容已经完结了,可能还有朋友说,你标题不是说的要讲一维表和二维表相互转换吗?怎么只讲了二维表到一维表?其实一维表到二维表是最简单的内容,在excel里主要涉及到就是透视表,而pandas也提供了类似透视表的功能, 那就是pivot_table函数。这个就可以留给朋友们自己去研究了。如果有需要可以关注公众号留言给我,我们在一篇文章里再讲讲。

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

推荐阅读更多精彩内容