在许多应⽤中,数据可能分散在许多⽂件或数据库中,存储的形式也不利于分析。本章关注可以聚合、合并、重塑数据的⽅法。
8.1层次化索引
data = pd.Series(np.random.randn(9),
...: index=[['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd', 'd'],
...: [1, 2, 3, 1, 3, 1, 2, 2, 3]])
data
data['b'] #得到参数是b的数
data['b':'c'] #得到参数是b和c的数
data.loc[['b', 'd']] #得到参数是b和d的数
data.loc[:, 2] # 得到内层参数是2的数
用unstack方法可以把数据变成DataFrane的形式,行名是abcd,列名是123
data.unstack()
data.unstack().stack() #stack是unstack的逆操作
DataFrame也有多层次索引的形式
frame = pd.DataFrame(np.arange(12).reshape((4, 3)),
....: index=[['a', 'a', 'b', 'b'], [1, 2, 1, 2]],
....: columns=[['Ohio', 'Ohio', 'Colorado'],
....: ['Green', 'Red', 'Green']])
frame.index.names = ['key1', 'key2'] #给index所在列命名key1和key2
frame.columns.names = ['state', 'color'] #给columns name所在行命名state和color
frame['Ohio'] #得到的列包含color所在行
MultiIndex.from_arrays([['Ohio', 'Ohio', 'Colorado'], ['Green', 'Red', 'Green']],
names=['state', 'color']) #创建多重索引的一种方法
8.1.1重新排序和排序级别
frame.swaplevel('key1', 'key2') #互换key1和key2
frame.sort_index(level=1) #索引的第二列进行排序
frame.swaplevel(0, 1).sort_index(level=0) #先互换索引的前两列再对索引的第一列进行排序
8.1.2按级别汇总统计
frame.sum(level='key2') #对索引列key2中相同索引的行进行加总
frame.sum(level='color', axis=1) #对相同颜色的列进行加总
## 8.1.3用DataFrame的columns来编制索引
frame = pd.DataFrame({'a': range(7), 'b': range(7, 0, -1),
....: 'c': ['one', 'one', 'one', 'two', 'two',
....: 'two', 'two'],
....: 'd': [0, 1, 2, 0, 1, 2, 3]})
frame2 = frame.set_index(['c', 'd']) #除去c和d两列并把c和d变成index,且索引c是one two
frame.set_index(['c', 'd'], drop=False) #添加参数drop,使得c,d两列不被删除
reset_index的作用和set_index相反,把多重索引变成columns
frame2.reset_index()
8.2合并和合并数据集
8.2.1数据库样式DataFrame链接
many to one join
df1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
'data1': range(7)})
df2 = pd.DataFrame({'key': ['a', 'b', 'd'],
'data2': range(3)})
pd.merge(df1, df2, on='key') # 默认参数how=inner,key取df1和df2都有的数
df3 = pd.DataFrame({'lkey': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
'data1': range(7)})
df4 = pd.DataFrame({'rkey': ['a', 'b', 'd'],
'data2': range(3)})
pd.merge(df3, df4, left_on='lkey', right_on='rkey') #两个列名不一样,比上面的情况不足之处在于列key变成了两列lkey和rkey,并且两列的值是一样的
pd.merge(df1, df2, how='outer') # key的值是df1和df2值的并集,结果是先把交集排完再排其他的
many to many join
df1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'b'],
'data1': range(6)})
In [46]: df2 = pd.DataFrame({'key': ['a', 'b', 'a', 'b', 'd'],
'data2': range(5)})
pd.merge(df1, df2, on='key', how='left')
pd.merge(df1, df2, how='inner')
有多个key时:
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')
pd.merge(left, right, on='key1')
pd.merge(left, right, on='key1', suffixes=('_left', '_right'))
8.2.2按索引合并
left1 = pd.DataFrame({'key': ['a', 'b', 'a', 'a', 'b', 'c'],
'value': range(6)})
right1 = pd.DataFrame({'group_val': [3.5, 7]}, index=['a', 'b'])
pd.merge(left1, right1, left_on='key', right_index=True) #用key来连接,其他的方法和many to one join一样
pd.merge(left1, right1, left_on='key', right_index=True, how='outer')
8.2.3轴向连接
另⼀种数据合并运算也被称作连接(concatenation)、绑定(binding)或堆叠(stacking)。
arr = np.arange(12).reshape((3, 4))
np.concatenate([arr, arr], axis=1) #按行连接在一起
s1 = pd.Series([0, 1], index=['a', 'b'])
s2 = pd.Series([2, 3, 4], index=['c', 'd', 'e'])
s3 = pd.Series([5, 6], index=['f', 'g'])
pd.concat([s1, s2, s3]) #按列连接在一起
pd.concat([s1, s2, s3], axis=1) #生成DataFrame
pd.concat([s1, s4], axis=1)
pd.concat([s1, s4], axis=1, join='inner') #加入参数join,删去了含有缺失值的行
result = pd.concat([s1, s1, s3], keys=['one', 'two', 'three']) #添加一层索引,变成层次化索引
result.unstack() #把层次化索引变成DataFrame的数据格式
pd.concat([s1, s2, s3], axis=1, keys=['one', 'two', 'three']) #参数key指定列名
df1 = pd.DataFrame(np.arange(6).reshape(3, 2), index=['a', 'b', 'c'],
columns=['one', 'two'])
df2 = pd.DataFrame(5 + np.arange(4).reshape(2, 2), index=['a', 'c'],
columns=['three', 'four'])
pd.concat([df1, df2], axis=1, keys=['level1', 'level2']) #按行连接,并且用参数key增加一层列名称
pd.concat({'level1': df1, 'level2': df2}, axis=1) #用字典的形式,得到的结果也是一样的
pd.concat([df1, df2], axis=1, keys=['level1', 'level2'],
names=['upper', 'lower']) #为列名称行添加名字
df1 = pd.DataFrame(np.random.randn(3, 4), columns=['a', 'b', 'c', 'd'])
df2 = pd.DataFrame(np.random.randn(2, 3), columns=['b', 'd', 'a'])
pd.concat([df1, df2], ignore_index=True) #按列连接
8.2.4合并重叠数据
还有⼀种数据组合问题不能⽤简单的合并(merge)或连接(concatenation)运算来处理。
a = pd.Series([np.nan, 2.5, np.nan, 3.5, 4.5, np.nan],
index=['f', 'e', 'd', 'c', 'b', 'a'])
b = pd.Series(np.arange(len(a), dtype=np.float64),
index=['f', 'e', 'd', 'c', 'b', 'a'])
b[-1] = np.nan
np.where(pd.isnull(a), b, a) #a和b的索引完全相同,每一个值都是取两者中的最大值
b[:-2].combine_first(a[2:]) #补上b[:-2]中没有且在a[2:]的index中的数
对于DataFrame的数据结构
df1 = pd.DataFrame({'a': [1., np.nan, 5., np.nan],
'b': [np.nan, 2., np.nan, 6.],
'c': range(2, 18, 4)})
df2 = pd.DataFrame({'a': [5., 4., np.nan, 3., 7.],
'b': [np.nan, 3., 4., 6., 8.]})
df1.combine_first(df2) #在df1中补上df1没有而df2有的部分
8.3重塑和轴向旋转
有许多⽤于重新排列表格型数据的基础运算。这些函数也称作重
塑(reshape)或轴向旋转(pivot)运算。
8.3.1重塑层次化索引
对于DataFrame,用stack将数据的列旋转为行,用unstack将数据的行旋转为列
data = pd.DataFrame(np.arange(6).reshape((2, 3)),
index=pd.Index(['Ohio', 'Colorado'], name='state'),
columns=pd.Index(['one', 'two', 'three'],
name='number'))
result = data.stack() #列转换为行
result.unstack() #回到原来的DataFrame的格式
result.unstack(0) # 看成是矩阵转置
result.unstack('state') #和上一个是一样的效果
s1 = pd.Series([0, 1, 2, 3], index=['a', 'b', 'c', 'd'])
s2 = pd.Series([4, 5, 6], index=['c', 'd', 'e'])
data2 = pd.concat([s1, s2], keys=['one', 'two']) #把s1和s2放在同一列上
data2.unstack() #把内侧index变成columns, 并且存在缺失值
data2.unstack().stack() #再次变成原来的,滤去缺失值
data2.unstack().stack(dropna=False) #把数值的两行变成一列
df = pd.DataFrame({'left': result, 'right': result + 5},
columns=pd.Index(['left', 'right'], name='side'))
df.unstack('state') #把外侧index变成columns
df.unstack('state').stack('side') #将side所在行变成内侧Index
8.3.2将“长格式”旋转为“宽格式”
多个时间序列数据通常是以所谓的“⻓格式”(long)或“堆叠格
式”(stacked)存储在数据库和CSV中的。我们先加载⼀些示例
数据,做⼀些时间序列规整和数据清洗:
data = pd.read_csv('examples/macrodata.csv')
data.head() #读取数据的前五行
8.3.3将“宽格式”旋转为“长格式”
旋转DataFrame的逆运算是pandas.melt。它不是将⼀列转换到
多个新的DataFrame,⽽是合并多个列成为⼀个,产⽣⼀个⽐输
⼊⻓的DataFrame。
df = pd.DataFrame({'key': ['foo', 'bar', 'baz'],
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, 8, 9]})
melted = pd.melt(df, ['key']) #key列是分组指标
reshaped = melted.pivot('key', 'variable', 'value') #重塑会原来的样子,并且把key列进行排序
reshaped.reset_index()
pd.melt(df, id_vars=['key'], value_vars=['A', 'B']) #用参数value_vars来指定列的子集
pd.melt(df, value_vars=['A', 'B', 'C']) #和上面类似,只是删去了列key
pd.melt(df, value_vars=['key', 'A', 'B'])