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

本文深入探讨了Pandas库中的高级数据处理技巧,包括数据的连接、合并、重塑以及处理重叠数据集的方法。通过实例展示了如何使用concat、combine_first、stack和unstack等函数来操作数据,实现数据的高效管理和分析。

Jupyter notebook】更好的阅读体验!

接上一部分


轴向连接

  • 另一种数据合并运算也被称作连接(concatenation)、绑定(binding)或堆叠(stacking)。NumPy的concatenation函数可以用NumPy数组来做:
import numpy as np
import pandas as pd
arr = np.arange(12).reshape((3,4))
arr
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
np.concatenate([arr,arr],axis=1)
array([[ 0,  1,  2,  3,  0,  1,  2,  3],
       [ 4,  5,  6,  7,  4,  5,  6,  7],
       [ 8,  9, 10, 11,  8,  9, 10, 11]])
np.concatenate([arr,arr],axis=0)
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

pandas 的concat()函数

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'])
# 使用concat可以将这些Series的值和索引连接起来
pd.concat([s1,s2,s3])
a    0
b    1
c    2
d    3
e    4
f    5
g    6
dtype: int64
  • 默认情况下是axis=0,也可以传入参数在列上合并,这样结果就会变成一个DataFrame
pd.concat([s1,s2,s3],axis=1,sort=False)
012
a0.0NaNNaN
b1.0NaNNaN
cNaN2.0NaN
dNaN3.0NaN
eNaN4.0NaN
fNaNNaN5.0
gNaNNaN6.0
s4 = pd.concat([s1,s3])
s4
a    0
b    1
f    5
g    6
dtype: int64
pd.concat([s1,s4],axis=1,sort=False)
01
a0.00
b1.01
fNaN5
gNaN6
pd.concat([s1,s4],axis=1,join='inner')
01
a00
b11
  • 通过join_axes指定要在其它轴上使用的索引:
pd.concat([s1,s4],axis=1, join_axes=[['a','c','b','e']])
01
a0.00.0
cNaNNaN
b1.01.0
eNaNNaN
#不过有个问题,参与连接的片段在结果中区分不开。
#假设你想要在连接轴上创建一个层次化索引。使用keys参数即可达到这个目的:
result = pd.concat([s1,s2,s3],keys = ['one','two','three'])
result
one    a    0
       b    1
two    c    2
       d    3
       e    4
three  f    5
       g    6
dtype: int64
result.unstack()
abcdefg
one0.01.0NaNNaNNaNNaNNaN
twoNaNNaN2.03.04.0NaNNaN
threeNaNNaNNaNNaNNaN5.06.0
  • 如果沿着axis=1 进行合并,则keys就会成为列头
pd.concat([s1,s2,s3],axis=1,keys=['one','two','three'],sort=False)
onetwothree
a0.0NaNNaN
b1.0NaNNaN
cNaN2.0NaN
dNaN3.0NaN
eNaN4.0NaN
fNaNNaN5.0
gNaNNaN6.0
  • 同样的逻辑也适用于DataFrame
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'])
df1
onetwo
a01
b23
c45
df2
threefour
a56
c78
pd.concat([df1,df2],axis=1,keys=['level1','level2'],sort=False)
level1level2
onetwothreefour
a015.06.0
b23NaNNaN
c457.08.0
  • 如果传入的不是一个列表,而是一个字典,那么字典的键就会被当作keys的选项
pd.concat({'level1':df1, 'level2':df2},axis=1,sort=False)
level1level2
onetwothreefour
a015.06.0
b23NaNNaN
c457.08.0
  • 此外还可以传入names参数
pd.concat([df1,df2],axis=1,keys=['level1','level2'],names=['upper','lower'],sort=False)
upperlevel1level2
loweronetwothreefour
a015.06.0
b23NaNNaN
c457.08.0
  • concat的参数如下:
    1

合并重叠数据集

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=a.index)
a
f    NaN
e    2.5
d    NaN
c    3.5
b    4.5
a    NaN
dtype: float64
b[-1]=np.nan
b
f    0.0
e    1.0
d    2.0
c    3.0
b    4.0
a    NaN
dtype: float64
np.where(pd.isnull(a),b,a)
array([0. , 2.5, 2. , 3.5, 4.5, nan])
b[:-2].combine_first(a[1:])
a    NaN
b    4.5
c    3.0
d    2.0
e    1.0
f    0.0
dtype: float64
  • 注: np.where(condition, x, y)满足condition则输出x,否则输出y.上面的代码:如果a的元素是nan则输出b对应的元素

  • 对于DataFrame,combine_first会做同样的事情

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
abc
01.0NaN2
1NaN2.06
25.0NaN10
3NaN6.014
df2
ab
05.0NaN
14.03.0
2NaN4.0
33.06.0
47.08.0
df1.combine_first(df2)
abc
01.0NaN2.0
14.02.06.0
25.04.010.0
33.06.014.0
47.08.0NaN

8.3重塑和轴向旋转

重塑层次化索引

  • 主要方法有:
    • stack():将列旋转为行
    • unstack():将行旋转为列
data = pd.DataFrame(np.arange(6).reshape((2,3)),
                   index=pd.Index(['Ohio','Colordo'],name='state'),
                   columns=pd.Index(['one','two','three'],name='number'))
data
numberonetwothree
state
Ohio012
Colordo345
result = data.stack()
result
state    number
Ohio     one       0
         two       1
         three     2
Colordo  one       3
         two       4
         three     5
dtype: int32
result.unstack()
numberonetwothree
state
Ohio012
Colordo345
  • 默认情况下,unstack操作的是最内层(stack也是如此)。传入分层级别的编号或名称即可对其它级别进行unstack操作:
result.unstack(0)
stateOhioColordo
number
one03
two14
three25
result.unstack('state')
stateOhioColordo
number
one03
two14
three25
  • 如果有的值找不到,就会引入缺失数据
s1 = pd.Series([0,1,2,3],index=['a','b','c','d'])
s2 = pd.Series([4,5,6],index=['c','d','e'])
data = pd.concat([s1,s2],keys=['one','two'])
data
one  a    0
     b    1
     c    2
     d    3
two  c    4
     d    5
     e    6
dtype: int64
data.unstack()
abcde
one0.01.02.03.0NaN
twoNaNNaN4.05.06.0
data.unstack().stack()
one  a    0.0
     b    1.0
     c    2.0
     d    3.0
two  c    4.0
     d    5.0
     e    6.0
dtype: float64
data.unstack().stack(dropna=False)
one  a    0.0
     b    1.0
     c    2.0
     d    3.0
     e    NaN
two  a    NaN
     b    NaN
     c    4.0
     d    5.0
     e    6.0
dtype: float64
  • DataFrame进行unstack操作时,作为旋转轴的级别将会成为结果中的最低级别:
df = pd.DataFrame({'left': result, 'right': result + 5},
                  columns=pd.Index(['left', 'right'], name='side'))
df
sideleftright
statenumber
Ohioone05
two16
three27
Colordoone38
two49
three510
df.unstack('state')
sideleftright
stateOhioColordoOhioColordo
number
one0358
two1469
three25710
# 调用stack()可以指明轴的名字
df.unstack('state').stack('side')
stateColordoOhio
numberside
oneleft30
right85
twoleft41
right96
threeleft52
right107

将长格式转换为宽格式

  • 多个时间序列数据通常是以所谓的“长格式”(long)或“堆叠格式”(stacked)存储在数据库和CSV中的。
data = pd.read_csv('data/examples/macrodata.csv')
data.head()
yearquarterrealgdprealconsrealinvrealgovtrealdpicpim1tbilrateunemppopinflrealint
01959.01.02710.3491707.4286.898470.0451886.928.98139.72.825.8177.1460.000.00
11959.02.02778.8011733.7310.859481.3011919.729.15141.73.085.1177.8302.340.74
21959.03.02775.4881751.8289.226491.2601916.429.35140.53.825.3178.6572.741.09
31959.04.02785.2041753.7299.356484.0521931.329.37140.04.335.6179.3860.274.06
41960.01.02847.6991770.5331.722462.1991955.529.54139.63.505.2180.0072.311.19
periods = pd.PeriodIndex(year=data.year,quarter=data.quarter,name='data')
columns = pd.Index(['realgdp','infl','unemp'],name='item')
data = data.reindex(columns=columns)
data.index = periods.to_timestamp('D','end')
ldata = data.stack().reset_index().rename(columns={0:'value'})
ldata[:5]
dataitemvalue
01959-03-31realgdp2710.349
11959-03-31infl0.000
21959-03-31unemp5.800
31959-06-30realgdp2778.801
41959-06-30infl2.340
pivoted = ldata.pivot('data','item','value')
pivoted[:5]
iteminflrealgdpunemp
data
1959-03-310.002710.3495.8
1959-06-302.342778.8015.1
1959-09-302.742775.4885.3
1959-12-310.272785.2045.6
1960-03-312.312847.6995.2

将宽格式旋转为长格式

df = pd.DataFrame({'key':['foo','bar','baz'],
                  'A':[1,2,3],
                  'B':[4,5,6],
                  'C':[7,8,9]})
df
keyABC
0foo147
1bar258
2baz369
melted = pd.melt(df,['key'])
melted
keyvariablevalue
0fooA1
1barA2
2bazA3
3fooB4
4barB5
5bazB6
6fooC7
7barC8
8bazC9
reshaped = melted.pivot('key','variable','value')
reshaped
variableABC
key
bar258
baz369
foo147
reshaped.reset_index()
variablekeyABC
0bar258
1baz369
2foo147
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值