复习:在前面我们已经学习了Pandas基础,第二章我们开始进入数据分析的业务部分,在第二章第一节的内容中,我们学习了数据的清洗,这一部分十分重要,只有数据变得相对干净,我们之后对数据的分析才可以更有力。而这一节,我们要做的是数据重构,数据重构依旧属于数据理解(准备)的范围。
开始之前,导入numpy、pandas包和数据
# 导入基本库
import numpy as np
import pandas as pd
# 载入data文件中的:train-left-up.csv
data_lu = pd.read_csv("data/train-left-up.csv")
data_lu.head(5)
PassengerId | Survived | Pclass | Name | |
---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina |
3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) |
4 | 5 | 0 | 3 | Allen, Mr. William Henry |
2 第二章:数据重构
2.4 数据的合并
2.4.1 任务一:将data文件夹里面的所有数据都载入,观察数据的之间的关系
#写入代码
data_ld = pd.read_csv("data/train-left-down.csv")
data_lu = pd.read_csv("data/train-left-up.csv")
data_rd = pd.read_csv("data/train-right-down.csv")
data_ru = pd.read_csv("data/train-right-up.csv")
#写入代码
data_ld.head(3),data_ld.tail(3),data_ld.shape
( PassengerId Survived Pclass Name
0 440 0 2 Kvillner, Mr. Johan Henrik Johannesson
1 441 1 2 Hart, Mrs. Benjamin (Esther Ada Bloomfield)
2 442 0 3 Hampe, Mr. Leon,
PassengerId Survived Pclass Name
449 889 0 3 Johnston, Miss. Catherine Helen "Carrie"
450 890 1 1 Behr, Mr. Karl Howell
451 891 0 3 Dooley, Mr. Patrick,
(452, 4))
data_lu.head(3),data_lu.tail(3),data_lu.shape
( PassengerId Survived Pclass \
0 1 0 3
1 2 1 1
2 3 1 3
Name
0 Braund, Mr. Owen Harris
1 Cumings, Mrs. John Bradley (Florence Briggs Th...
2 Heikkinen, Miss. Laina ,
PassengerId Survived Pclass Name
436 437 0 3 Ford, Miss. Doolina Margaret "Daisy"
437 438 1 2 Richards, Mrs. Sidney (Emily Hocking)
438 439 0 1 Fortune, Mr. Mark,
(439, 4))
data_rd.head(3),data_rd.tail(3),data_rd.shape
( Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 male 31.0 0 0 C.A. 18723 10.50 NaN S
1 female 45.0 1 1 F.C.C. 13529 26.25 NaN S
2 male 20.0 0 0 345769 9.50 NaN S,
Sex Age SibSp Parch Ticket Fare Cabin Embarked
449 female NaN 1 2 W./C. 6607 23.45 NaN S
450 male 26.0 0 0 111369 30.00 C148 C
451 male 32.0 0 0 370376 7.75 NaN Q,
(452, 8))
data_ru.head(3),data_ru.tail(3),data_ru.shape
( Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 male 22.0 1 0 A/5 21171 7.2500 NaN S
1 female 38.0 1 0 PC 17599 71.2833 C85 C
2 female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S,
Sex Age SibSp Parch Ticket Fare Cabin Embarked
436 female 21.0 2 2 W./C. 6608 34.375 NaN S
437 female 24.0 2 3 29106 18.750 NaN S
438 male 64.0 1 4 19950 263.000 C23 C25 C27 S,
(439, 8))
【提示】结合之前我们加载的train.csv数据,大致预测一下上面的数据是什么
答:根据ld和lu两张表可以看出,在PassengerId一列中,是呈升序且连续的特点,可以推测是同一组数据的拆分;
根据rd和ru两张表可以看出,它们包含的列数以及列名是一样的,且其行数分别与ld和lu对应,可推测是同一组数据的拆分,且与ld与lu是左右拼接的关系。因此拼接关系如下:
lu-ld
ru-rd
2.4.2:任务二:使用concat方法:将数据train-left-up.csv和train-right-up.csv横向合并为一张表,并保存这张表为result_up
pd.concat(objs, axis=0, join=“outer”, ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, copy=True)
参数:
- objs:需要连接的Series或DataFrame对象列表或字典。
如果传入的是字典,排序后的键将作为keys参数的值,除非keys参数已经指定了
任何None对象都将被无声地丢弃,如果它们全部都是None,在这种情况下,将会抛出ValueError异常 - axis:=0表示按行拼接(纵向),=1表示按列拼接(横向)。默认=0
- join:=“outer”表示并集,“inner”表示交集。默认=“outer”
- ignore_index:bool,默认为False。如果为True,则在串联轴上的索引值将标记为0,…,n-1
- keys:序列,默认为None。使用传递的键作为构建索引的最外成level。如果传递了多个层次,应该是用元组列表。
- levels:序列,默认为None。用于构建multiIndex的特定级别,否则它们将从keys中推断出来
- names:列表,默认为None。层次索引中的层次名字
- verify_integrity:bool,默认为False。检查新连接的轴是否包含重复的数据
- copy:bool,默认为True。如果为False,则非必要的时候不复制数据
#写入代码
result_up = pd.concat([data_lu,data_ru],axis = 1)
result_up.head(3)
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
2.4.3 任务三:使用concat方法:将train-left-down和train-right-down横向合并为一张表,并保存这张表为result_down。然后将上边的result_up和result_down纵向合并为result。
#写入代码
result_down = pd.concat([data_ld,data_rd], axis = 1)
result_down.head(3)
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 440 | 0 | 2 | Kvillner, Mr. Johan Henrik Johannesson | male | 31.0 | 0 | 0 | C.A. 18723 | 10.50 | NaN | S |
1 | 441 | 1 | 2 | Hart, Mrs. Benjamin (Esther Ada Bloomfield) | female | 45.0 | 1 | 1 | F.C.C. 13529 | 26.25 | NaN | S |
2 | 442 | 0 | 3 | Hampe, Mr. Leon | male | 20.0 | 0 | 0 | 345769 | 9.50 | NaN | S |
result = pd.concat([result_up, result_down], axis = 0)
result.shape
(891, 12)
2.4.4 任务四:使用DataFrame自带的方法join方法和append:完成任务二和任务三的任务
str.join(sequence)
将序列sequence(也就是字符串、元组、列表、字典)中的元素以指定的字符str连接生成一个新的字符串。
#写入代码
result_up = data_lu.join(data_ru)
result_up.head(3)
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
result_down = data_ld.join(data_rd)
result_down.head(3)
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 440 | 0 | 2 | Kvillner, Mr. Johan Henrik Johannesson | male | 31.0 | 0 | 0 | C.A. 18723 | 10.50 | NaN | S |
1 | 441 | 1 | 2 | Hart, Mrs. Benjamin (Esther Ada Bloomfield) | female | 45.0 | 1 | 1 | F.C.C. 13529 | 26.25 | NaN | S |
2 | 442 | 0 | 3 | Hampe, Mr. Leon | male | 20.0 | 0 | 0 | 345769 | 9.50 | NaN | S |
result = result_up.append(result_down)
result.shape
(891, 12)
**【VC小注】**join方法实现左右连接,append实现上下连接
2.4.5 任务五:使用Panads的merge方法和DataFrame的append方法:完成任务二和任务三的任务
pd.merge(left, right, how=“inner”, on = None, left_on=None, right_on=None, left_index=False, right_index=False, sort=True, suffices=(“_x”,“_y”), copy=True, indicator=False)
参数:
- left:参与合并的左侧DataFrame;
- right:参与合并的右侧DataFrame;
- how:连接方式,有inner(交集)、left(以左边的表为参考合并,缺失数据范围NaN填充)、right(以右边的表为参考合并,缺失数据范围NaN填充)、outer(并集,缺失数据用NaN填充),默认为inner;
- on:指的是用于连接的列索引名称,必须存在于左右两个DataFrame中,如果没有指定且其他参数也没有指定,则以两个DataFrame列名交集作为连接键;
- left_on:左侧DataFrame中用于连接键的列名,这个参数左右列名不同但代表的含义相同时非常的有用;
- right_on:右侧DataFrame中用于连接键的列名;
- left_index:使用左侧DataFrame中的行索引作为连接键;
- right_index:使用右侧DataFrame中的行索引作为连接键;
- sort:默认为True,将合并的数据进行排序,设置为False可以提高性能;
- suffixes:字符串值组成的元组,用于指定当左右DataFrame存在相同列名时在列名后面附加的后缀名称,默认为(‘_x’, ‘_y’);
- copy:默认为True,总是将数据复制到数据结构中,设置为False可以提高性能;
- indicator:显示合并数据中数据的来源情况。
**【注】**左右连接键名不同或是以行索引为连接键时,要同时说明左右连接键(left_on 或 left_index,right_on 或 right_index);若以共有的列索引进行连接,可用on直接说明。
#写入代码
result_up = pd.merge(data_lu, data_ru, left_index = True, right_index = True)
result_up.head(3)
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
result_down = pd.merge(data_ld, data_rd, left_index = True, right_index = True)
result_down.head(3)
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 440 | 0 | 2 | Kvillner, Mr. Johan Henrik Johannesson | male | 31.0 | 0 | 0 | C.A. 18723 | 10.50 | NaN | S |
1 | 441 | 1 | 2 | Hart, Mrs. Benjamin (Esther Ada Bloomfield) | female | 45.0 | 1 | 1 | F.C.C. 13529 | 26.25 | NaN | S |
2 | 442 | 0 | 3 | Hampe, Mr. Leon | male | 20.0 | 0 | 0 | 345769 | 9.50 | NaN | S |
result_up.append(result_down)
result.shape
(891, 12)
【思考】对比merge、join以及concat的方法的不同以及相同。思考一下在任务四和任务五的情况下,为什么都要求使用DataFrame的append方法,如何只要求使用merge或者join可不可以完成任务四和任务五呢?
答:
同:三种方法都可以实现表格数据的连接
异:concat可以实现表格上下左右的连接,使用axis参数即可改变连接方向;而merge和join只能实现左右连接
此外,concat和join只是单纯将数据拼接起来,merge可以实现通过索引的连接,类似SQL
若只使用merge或join方法,或许可以将表格进行转置,将上下连接转换成左右连接,然后再进行转置得到最终结果
**【注】**转置后要注意修改列名,否则会报错,因为原行索引都是从0开始,转置后变成列名,要将后表的列名进行顺延,否则会报错
df.T 可以实现对表格数据的转置
result_up_T = result_up.T
result_down_T = result_down.T
result_down_T.columns = [str(i) for i in range(result_up_T.columns.size, result_up_T.columns.size+result_down_T.columns.size)] #修改后表列名
result_T = result_up_T.join(result_down_T)
result = result_T.T
result.head(5)
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22 | 1 | 0 | A/5 21171 | 7.25 | NaN | S |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26 | 0 | 0 | STON/O2. 3101282 | 7.925 | NaN | S |
3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35 | 1 | 0 | 113803 | 53.1 | C123 | S |
4 | 5 | 0 | 3 | Allen, Mr. William Henry | male | 35 | 0 | 0 | 373450 | 8.05 | NaN | S |
2.4.6 任务六:完成的数据保存为result.csv
#写入代码
result.to_csv("result.csv")
2.5 换一种角度看数据
2.5.1 任务一:将我们的数据变为Series类型的数据
【总结】数据堆叠—stack和unstack函数的使用及区别
在分类汇总数据中,stack() 和 unstack() 是进行层次化索引的重要操作。
层次化索引就是对索引进行层次化分类,包含行索引、列索引。
常见的数据层次化结构包含两种:表格(横表)、花括号(纵表)。
表格在行列方向上均有索引,花括号结构只有列方向上的索引。
DataFrame.stack(level=-1, dropna=True)
DataFrame.unstack(level=-1, fill_value=None)
stack —— 将数据从“表格结构”变成“花括号结构”,即将其列索引变成行索引。
unstack —— 数据从“花括号结构”变成“表格结构”,即要将其中一层的行索引变成列索引。
如果是多层索引,则以上函数是针对内层索引,利用 level 参数可以选择具体哪层索引。
【小技巧】使用 stack() 的时候,level 等于哪一个,哪一个就消失,出现在行里。
【小技巧】使用 unstack() 的时候,level 等于哪一个,哪一个就消失,出现在列里。
【参考】
http://t.zoukankan.com/hider-p-15309859.html
#写入代码
result = pd.read_csv("result.csv")
result2s = result.stack(dropna = False)
result2s
0 Unnamed: 0 0
PassengerId 1
Survived 0
Pclass 3
Name Braund, Mr. Owen Harris
...
890 Parch 0
Ticket 370376
Fare 7.75
Cabin NaN
Embarked Q
Length: 11583, dtype: object
result2s = pd.Series(result.T.unstack())
result2s
0 Unnamed: 0 0
PassengerId 1
Survived 0
Pclass 3
Name Braund, Mr. Owen Harris
...
890 Parch 0
Ticket 370376
Fare 7.75
Cabin NaN
Embarked Q
Length: 11583, dtype: object
#写入代码
result2s.to_csv("result2s.csv")