1 数据的合并
1.1 加载数据并使用不同的方法合并
import numpy as np
import pandas as pd
#加载数据
text_left_up = pd.read_csv("data/train-left-up.csv")
text_left_down = pd.read_csv("data/train-left-down.csv")
text_right_up = pd.read_csv("data/train-right-up.csv")
text_right_down = pd.read_csv("data/train-right-down.csv")
四个表分别为:
其实就是泰坦尼克号数据的左上、左下、右上、右下四个部分
1.1.1 concat
concat默认上下拼接
pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, copy=True)
主要参数
参数 | 说明 |
---|---|
objs | 需要连接的对象,eg [df1, df2] |
axis | axis = 0, 表示在水平方向(row)进行连接 axis = 1, 表示在垂直方向(column)进行连接 |
拼接左上和右上
#使用concat方法:将数据train-left-up.csv和trainright-up.csv横向合并为一张表,并保存这张表为result_up
list_up = [text_left_up, text_right_up]
result_up = pd.concat(list_up, axis=1)
result_up.head()
1.1.2 join
DataFrame.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False)
在索引或键列上将列与其他 DataFrame连接起来。
#使用DataFrame自带的方法join方法和append:完成任务二和任务三的任务
result_up = text_left_up.join(text_right_up)
这里join似乎只能横向拼接,上下拼接需要使用额外的append()方法
result = result_up.append(result_down)
1.1.3 merge
pandas.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes='_x', '_y', copy=True, indicator=False, validate=None)
参数说明
对两个DataFrame,data1和data2进行merge操作,默认的调用形式是pd.merge(data1, data2)。
result_up = pd.merge(text_left_up, text_right_up, left_index=True, right_index=True)
result_down = pd.merge(text_left_down, text_right_down, left_index=True, right_index=True)
result = result = result_up.append(result_down)
同样只能左右拼接,上下拼接需要使用append()。
如果没有指明要用哪个列进行连接,merge就会将重叠列的列名当做键。
#df1
data1 key
0 0 b
1 1 b
2 2 a
3 3 c
4 4 a
5 5 a
6 6 b
#df2
data2 key
0 0 a
1 1 b
2 2 d
pd.merge(df1, df2)
data1 key data2
0 0 b 1
1 1 b 1
2 6 b 1
3 2 a 0
4 4 a 0
5 5 a 0
默认情况下,merge做的是“内连接”;结果中的键是交集。可以通过修改参数how使用其他方式,参数如下
pd.merge(df1, df2, how='outer')#外连接求并集
key data1 data2
0 b 0.0 1.0
1 b 1.0 1.0
2 b 6.0 1.0
3 a 2.0 0.0
4 a 4.0 0.0
5 a 5.0 0.0
6 c 3.0 NaN
7 d NaN 2.0
结合了左连接和右连接的效果。
如果两个对象的列名不同,也可以分别进行指定:
#df3
lkey data1
0 b 0
1 b 1
2 a 2
3 c 3
4 a 4
5 a 5
6 b 6
#df4
rkey data2
0 a 0
1 b 1
2 d 2
pd.merge(df3, df4, left_on='lkey', right_on='rkey')
lkey data1 rkey data2
0 b 0 b 1
1 b 1 b 1
2 b 6 b 1
3 a 2 a 0
4 a 4 a 0
5 a 5 a 0
默认求并集,结果里面c和d以及与之相关的数据消失了。
上述是多对一的例子(多个key对一个key),多对多的不太直观,看一个例子
#df1
data1 key
0 0 b
1 1 b
2 2 a
3 3 c
4 4 a
5 5 b
#df2
data2 key
0 0 a
1 1 b
2 2 a
3 3 b
4 4 d
pd.merge(df1, df2, on='key', how='left')
data1 key data2
0 0 b 1
1 0 b 3
2 1 b 1
3 1 b 3
4 5 b 1
5 5 b 3
6 2 a 0
7 2 a 2
8 4 a 0
9 4 a 2
多对多连接产生的是行的笛卡尔积。由于左边的DataFrame有3个"b"行,右边的有2个,所以最终结果中就有6个"b"行。
要根据多个键进行合并,也可以传入一个由列名组成的列表
left = pd.DataFrame({'key1': ['foo', 'foo', 'bar'],
'key2': ['one', 'two', 'one'],
'lval': [1, 2, 3]})
right = pd.DataFrame({'key1': ['foo', 'foo', 'bar', 'bar'],
'key2': ['one', 'one', 'one', 'two'],
'rval': [4, 5, 6, 7]})
pd.merge(left, right, on=['key1', 'key2'], how='outer')
key1 key2 lval rval
0 foo one 1.0 4.0
1 foo one 1.0 5.0
2 foo two 2.0 NaN
3 bar one 3.0 6.0
4 bar two NaN 7.0
2 重塑层次化索引
层次化索引为DataFrame数据的重排任务提供了一种具有良好一致性的方式。主要功能有二:
stack:将数据的列“旋转”为行。
unstack:将数据的行“旋转”为列。
stack()可以将列转换为行,得到一个Series
#将我们的数据变为Series类型的数据
text = pd.read_csv('result.csv')
unit_result = text.stack()#stack:将数据的列“旋转”为行,得到一个Series
unit_result.head()
unstack将其重排为一个DataFrame
3 数据聚合与运算
使用groupby机制。
#df
key1 key2 data1 data2
0 a one -0.232469 0.639014
1 a two 1.919082 -0.190552
2 b one -1.717775 0.674685
3 b two -1.218958 -1.228822
4 a one 2.363391 0.161266
分组求均值
#按key1进行分组,并计算data1列的平均值
grouped = df['data1'].groupby(df['key1'])
grouped.mean()
可传入多个分组
means = df['data1'].groupby([df['key1'], df['key2']]).mean()
列名作为分组键
#将列名(可以是字符串、数字或其他Python对象)用作分组键
df.groupby(['key1', 'key2']).mean()
获取分组大小
df.groupby(['key1', 'key2']).size()#返回一个含有分组大小的Series,缺失值都会被从结果中除去
支持迭代
#GroupBy对象支持迭代
for name, group in df.groupby('key1'):
print(name)
print(group)
实际应用
#计算泰坦尼克号男性与女性的平均票价
means = result['Fare'].groupby(result['Sex']).mean()
means
#统计泰坦尼克号中男女的存活人数
survives = result['Survived'].groupby(result['Sex']).sum()
survives
#计算客舱不同等级的存活人数
result['Survived'].groupby(result['Pclass']).sum()
女性票价比较贵,存活率也比男性高(所以是因为票价高呢还是因为女士优先呢),船舱等级最高的存活率也最高,但是第二级的存活率反而垫底(可能男的比较多?)
使用agg()可以使用自己编写的函数
def mysum(arr):
return arr.sum()
result['Survived'].groupby(result['Pclass']).agg(mysum)
使用多个列名作为索引键
#统计在不同等级的票中的不同年龄的船票花费的平均值
result.groupby(['Pclass', 'Age'])[['Fare']].mean().head()
合并票价均值和男女存活人数
text = pd.merge(means, survives, on='Sex')#合并两个具有相同列索引的series
计算不同年龄的总的存活人数,然后找出存活人数的最高的年龄,最后计算存活人数最高的存活率(存活人数/总人数)
##不同年龄的存活人数
survied_age = result['Survived'].groupby(result['Age']).sum()
#找出存活人数最大值的年龄
survied_age[survied_age.values == survied_age.max()]
#计算存活人数
survied_sum = result['Survived'].sum()
#计算最高存活率
survied_age.max() / survied_sum
其中24岁的存活人数最多,有15个,在总存活人数342中占0.04385。