数据规整:聚合、合并和重塑

本章介绍了数据规整的各种方法,包括层次化索引的使用,如重新排序和按级别汇总统计;数据集的合并,如数据库样式的DataFrame链接、按索引合并和轴向连接;以及数据的重塑和轴向旋转,涉及长格式与宽格式之间的转换。这些技巧对于整理分散且不利于分析的数据至关重要。
摘要由CSDN通过智能技术生成

在许多应⽤中,数据可能分散在许多⽂件或数据库中,存储的形式也不利于分析。本章关注可以聚合、合并、重塑数据的⽅法。

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']) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值