Pandas数据重塑与透视

深入浅出Pandas读书笔记

C9 Pandas数据重塑与透视

9.1 数据透视

9.1.1 整理透视 df.pivot()

要实现基础的透视操作, 可以使用df.pivot()返回按给定的索引, 列值重新组织整理后的DataFrame. df.pivot()有3个参数, 这些参数传入的值是原数据的列名, 作用分别为

  • index 作为新DataFrame的索引, 取分组去重的值, 如果不传入, 取现有索引
  • columns 作为新DataFrame的列, 取去重的值, 当列和索引的组合有多个值的时候会报错(需要使用聚合函数, pivot只负责重塑, 没有聚合功能), 需要使用df.pivot_table()进行操作
  • values 作为新DataFrame()的值, 如果指定多个, 会形成多层索引, 如果不指定, 会默认人为所有剩余的列

9.1.2 整理透视操作

df = pd.DataFrame({"A": ['a1', 'a1', 'a2', 'a3', 'a3', 'a3'],
                   'B': ['b1', 'b2', 'b3', 'b1', 'b2', 'b3'],
                   'C': ['c1', 'c2', 'c3', 'c4', 'c5', 'c6'],
                   'D': ['d1', 'd2', 'd3', 'd4', 'd5', 'd6'],
                  })
df.pivot(index='A', columns='B', values='C') # A与B没有重复值, 将A列去重作为索引, B列去重作为列, 取C的内容作为具体的数据值
'''
B	b1	b2	b3
A			
a1	c1	c2	NaN
a2	NaN	NaN	c3
a3	c4	c5	c6
'''

9.1.3 聚合透视

df.pivot()只是对原数据的结构, 显示做了变换, 在实现业务中, 往往还需要在数据透视过程中对值进行计算, 这时候就要用到pd.pivot_table()
pd.pivot_table()有以下几个关键参数

  • data
  • index
  • values 要聚合的值
  • columns 要聚合的列
  • aggfunc 聚合函数
  • fill_value
  • margins 是否增加汇总行列

9.1.4 聚合透视操作

df = pd.DataFrame({"A": ['a1', 'a1', 'a1', 'a2', 'a2', 'a2'],
                   'B': ['b2', 'b2', 'b1', 'b1', 'b1', 'b1'],
                   'C': ['c1', 'c1', 'c2', 'c2', 'c1', 'c1'],
                   'D': [1, 2, 3, 4, 5, 6],
                  })
# 如果对以上数据进行以A为索引, 以B为列的透视df.pivot(), 会报错, 因为索引和列组合后有重复数据, 涉及到聚合操作, 需要使用pd.pivot_table()
df.pivot_table(index='A', columns='B', values='D') # 默认求mean

9.1.5 聚合透视高级操作

df.pivot_table(index=['A', 'B'], columns='C', values='D', aggfunc=np.sum, fill_value=0, margins=True)
# 使用多个计算方法
df.pivot_table(index=['A', 'B'], columns='C', values='D', aggfunc=[np.mean, np.sum])
# 为每一列指定不同的计算方法
df = pd.DataFrame({
    'A': ['a1', 'a1', 'a1', 'a2', 'a2', 'a2'],
    'B': ['b2', 'b2', 'b1', 'b1', 'b1', 'b1'],
    'C': ['c1', 'c1', 'c2', 'c2', 'c1', 'c1'],
    'D': [1, 2, 3, 4, 5, 6],
    'E': [9, 8, 7, 6, 5, 4]
})
df.pivot_table(index=['A', 'B'], columns='C', aggfunc={'D': np.mean, 'E': np.sum})
df.pivot_table(index=['A', 'B'], columns='C', aggfunc={'D': [np.mean], 'E': np.sum}) # 在aggfunc内的函数中加入[], 在现实中会把函数名显示出

9.2 数据堆叠

9.2.1 理解堆叠

堆叠stack的过程表示将数据列的所有数据表全部旋转到列上
解堆unstack的过程表示将在行上的索引旋转到列上

  • 堆叠: 透视某个级别的列标签, 返回带有索引的DataFrame, 该索引带有一个新的行标签, 这个新标签在原有索引的左右边
  • 解堆: 将航索引的某个级别透视到列轴, 从而生成具有新的最里面的列标签级别的重构的DataFrame
    堆叠过程将数据集的列转行, 解堆过程为行转列

9.2.2 堆叠操作 df.stack()

df = pd.DataFrame({
    'A': ['a1', 'a1', 'a2', 'a2'],
    'B': ['b1', 'b2', 'b1', 'b2'],
    'C': [1, 2, 3, 4],
    'D': [5, 6, 7, 8],
    'E': [5, 6, 7, 8]
})
df.set_index(['A', 'B'], inplace=True)
df.stack()
'''
A   B    
a1  b1  C    1
        D    5
        E    5
    b2  C    2
        D    6
        E    6
a2  b1  C    3
        D    7
        E    7
    b2  C    4
        D    8
        E    8
dtype: int64
'''
type(df.stack()) # pandas.core.series.Series

9.2.3 解堆操作 df.unstack()

df.stack().unstack()
'''
		C	D	E
A	B			
a1	b1	1	5	5
b2	2	6	6
a2	b1	3	7	7
b2	4	8	8
'''

9.3 交叉表 crosstab

交叉表就是将两列或多列中不重复的元素组成一个新的DataFrame, 新数据的行和列交叉部分的值为其组合在原数据中的数量

9.3.1 基本语法

pd.crosstab(index, columns, values=None, rownames=None, colnames=None, aggfunc=None, margins=False, 
            margins_name: str='All', dropna: bool=True, normalize=False
)

参数说明如下

  • index
  • columns
  • values
  • aggfunc
  • rownames 新行名
  • colnames 新列名
  • margins
  • normalize 布尔值, {‘all’, ‘index’ ‘columns’} 或 {0, 1}, 默认值为False, 通过将所有值除以值的总和进行归一化

9.3.2 生成交叉表

df = pd.DataFrame({
    'A': ['a1', 'a1', 'a2', 'a2', 'a1'],
    'B': ['b2', 'b1', 'b2', 'b2', 'b1'],
    'C': [1, 2, 3, 4, 5],
})
pd.crosstab(df.A, df.B)
'''
B	b1	b2
A		
a1	2	1
a2	0	2
'''

9.3.3 归一化

# 整体中的占比
pd.crosstab(df.A, df.B, normalize=True)
# 在列中的占比
pd.crosstab(df.A, df.B, normalize='columns')

9.3.4 指定聚合方法

9.3.5 汇总

9.4 数据转置 df.T

9.4.1 数据转置

9.4.2 转置操作

9.4.3 类型变化

9.4.4 轴交换 df.swapaxes()

9.5 数据融合 df.melt()

9.5.1 基本语法

pd.melt(frame, id_vars=None, value_vars=None, var_name='variable', value_name='value', col_level=None)
)

参数说明

  • id_vars: 需要作为表示的列
  • value_vars: 需要堆起来的列, 如果不指定, 则使用未设置为id_vars的所有列
  • var_name
  • value_name
  • col_level

9.5.2 融合操作

df = pd.DataFrame({
    'A': ['a1', 'a2', 'a3', 'a4', 'a5'],
    'B': ['b1', 'b2', 'b3', 'b4', 'b5'],
    'C': [1, 2, 3, 4, 5]
})
df.melt()
'''
variable	value
0	A	a1
1	A	a2
2	A	a3
3	A	a4
4	A	a5
5	B	b1
6	B	b2
7	B	b3
8	B	b4
9	B	b5
10	C	1
11	C	2
12	C	3
13	C	4
14	C	5
'''

9.5.3 标识和值

9.5.4 指定名称

df.melt(id_vars=['A'], value_vars=['B'], var_name='Blabel', value_name='B_value')

9.6 虚拟变量 pd.get_dummies() -> one-hot编

虚拟变量(Dummy Variable)又称虚设变量, 名义变量或哑变量, 是一个用来反映质的属性的人工变量, 是量化了的自变量, 通常取值为0或1, 常被用于one-hot特征提取

9.6.1 语法结构

pd.get_dummies(data, prefix=None, prefix_sep='_', dummy_na=False, columns=None, sparse=False, drop_first=False, dtype=None)

9.6.2 生成虚拟变量

df = pd.DataFrame({
    'a': list('abcd'), 
    'b': list('fehg'), 
    'a1': range(4), 
    'b1': range(4, 8)})
# 对a进行one-hot操作
pd.get_dummies(df.a)
'''
a	b	c	d
0	1	0	0	0
1	0	1	0	0
2	0	0	1	0
3	0	0	0	1
'''

9.6.3 列前缀

9.6.4 从DataFrame生成

# 保持其他列的情况下, 对a进行one-hot
pd.get_dummies(df, columns=['a']) # 只对a进行one-hot处理
'''
	b	a1	b1	a_a	a_b	a_c	a_d
0	f	0	4	1	0	0	0
1	e	1	5	0	1	0	0
2	h	2	6	0	0	1	0
3	g	3	7	0	0	0	1
'''

9.7 因子化

因子化是指讲一个存在大量重复值的一维数据解析成枚举值的过程, 这样可以方便我们进行分辨. factorize既可以用作顶层函数pd.factorize(), 也可以用作Series.factorize()Index.factorize()方法

9.7.1 基本方法

对数据因子化后返回两个值, 一个是因子化后的编码列表, 另一个是原数据的去重值列表

data = ['b', 'b', 'a', 'c', 'b']
pd.factorize(data) # 返回编码, 和去重置
'''
(array([0, 0, 1, 2, 0], dtype=int64), array(['b', 'a', 'c'], dtype=object))
'''
# 
cat = pd.Series(['a', 'a', 'c'])
codes, uniques = pd.factorize(cat)
codes, uniques
'''
(array([0, 0, 1], dtype=int64), Index(['a', 'c'], dtype='object'))
'''

9.7.2 排序

codes, uniques = pd.factorize(['b', 'b', 'a', 'c', 'b'], sort=True)
codes, uniques
'''
(array([1, 1, 0, 2, 1], dtype=int64), array(['a', 'b', 'c'], dtype=object))
'''

9.7.3 缺失值

# 缺失值不会出现在唯一值列表中, 在编码中将为-1
codes, uniques = pd.factorize(['b', None, 'a', 'c', 'b'], sort=True)
codes, uniques
'''
(array([ 1, -1,  0,  2,  1], dtype=int64),
 array(['a', 'b', 'c'], dtype=object))
'''

9.7.4 枚举类型

Pandas的枚举类型数据Categorical也可以使用此方法

小结

因子化方法pd.factorize()做了两件事, 一是对数据进行数字编码, 二是对数据进行去重, 在大序列数据中, 因子化能帮助我们抽取数据特征, 将数据变成类别数据再进行分析.

9.8 爆炸列表

将类似列表每个元素转换为一行, 索引值是相同的

9.8.1 基本功能

s = pd.Series([[1, 2, 3], 'foo', [], [3, 4]])
s.explode()
'''
0      1
0      2
0      3
1    foo
2    NaN
3      3
3      4
dtype: object
'''
# 每行列表中的元素都独占了一行, 而索引保持不变, 空列表变成了NaN

9.8.2 DataFrame的爆炸

df = pd.DataFrame({'A': [[1, 2, 3], 'foo', [], [3, 4]], 'B': range(4)})
df.explode('A')
'''
A	B
0	1	0
0	2	0
0	3	0
1	foo	1
2	NaN	2
3	3	3
3	4	3
'''

9.8.3 非列表格式

df = pd.DataFrame([{'var1': 'a, b, c', 'var2': 1}, {'var1': 'd, e, f', 'var2': 2}])
'''
var1	var2
0	a, b, c	1
1	d, e, f	2
'''
df.assign(var1=df.var1.str.split(',')).explode('var1')
'''
	var1	var2
0	a	1
0	b	1
0	c	1
1	d	2
1	e	2
1	f	2
'''
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值