Pandas 行列转换
1.pivot_table
创建一个电子表格风格的数据透视表作为数据帧。
数据透视表中的级别将存储在结果DataFrame的索引和列上的MultiIndex对象(分层索引)中。
pd.pivot_table(data, # 制作透视表的数据
values=None, # 值
index=None, # 行索引
columns=None, # 列属性
aggfunc='mean', # 使用的函数,默认是均值
fill_value=None, # 缺失值填充
margins=False, # 是否显示总计
dropna=True, # 缺失值处理
margins_name='All', # 总计显示为All
observed=False,
sort=True # 排序功能
)
1.1第一个示例通过求和聚合值
df = pd.DataFrame({"A": ["foo", "foo", "foo", "foo", "foo",
"bar", "bar", "bar", "bar"],
"B": ["one", "one", "one", "two", "two",
"one", "one", "two", "two"],
"C": ["small", "large", "large", "small",
"small", "large", "small", "small",
"large"],
"D": [1, 2, 2, 3, 3, 4, 5, 6, 7],
"E": [2, 4, 5, 5, 6, 6, 8, 9, 9]})
import numpy as np
table = pd.pivot_table(df, values='D', index=['A', 'B'],
columns=['C'], aggfunc=np.sum)
table
1.2可以使用fill_value参数来填充缺失的值。
table = pd.pivot_table(df, values='D', index=['A', 'B'],
columns=['C'], aggfunc=np.sum, fill_value=0)
table
1.3下一个示例通过计算多个列的平均值进行聚合。
table = pd.pivot_table(df, values=['D', 'E'], index=['A', 'C'],
aggfunc={'D': np.mean,
'E': np.mean})
table
1.4计算任意给定值列的多种聚合类型。
table = pd.pivot_table(df, values=['D', 'E'], index=['A', 'C'],
aggfunc={'D': np.mean,
'E': [min, max, np.mean]})
table
2.cross_tab
计算两个(或更多)因子的简单交叉表。默认情况下,除非传递值数组和聚合函数,否则计算因子的频率表。
pandas.crosstab(index, # 行索引,必须是数组结构数据,或者Series,或者是二者的列表形式
columns, # 列字段;数据要求同上
values=None, # 待透视的数据
rownames=None, # 行列名字
colnames=None,
aggfunc=None, # 透视的函数
margins=False, # 汇总及名称设置
margins_name='All',
dropna=True, # 舍弃缺失值
normalize=False # 数据归一化;可以是布尔值、all、index、columns、或者{0,1}
)
2.1示例
import pandas as pd
df = pd.DataFrame(columns=['date','type','value'])
df['date'] = ['2022-1-{}'.format(i+1) for i in range(3)]*2
df['date'] = pd.to_datetime(df.date)
df['type'] = list('abcaac')
df.value = [2022,1,20,11,11,9]
df
cross_tab = pd.crosstab(index=df.date,columns=df.type,values=df.value,aggfunc='mean')
cross_tab
3.gropyby
df.groupby(['date','type'])['value'].mean().unstack()
4.melt
这个函数很有用,可以将DataFrame转换为一种格式,其中一列或多列是标识符变量(id_vars),而所有其他列,被认为是测量变量(value_vars),被“unpivot”到行轴,只留下两个非标识符列,‘variable’和‘value’。
pandas.melt(frame,
id_vars=None,
value_vars=None,
var_name=None,
value_name='value',
ignore_index=True,
col_level=None)
- frame:要处理的数据框DataFrame。
- id_vars:表示不需要被转换的列名
- value_vars:表示需要转换的列名,如果剩下的列全部都需要进行转换,则不必写
- var_name和value_name:自定义设置对应的列名,相当于是取新的列名
- igonore_index:是否忽略原列名,默认是True,就是忽略了原索引名,重新生成0,1,2,3,4....的自然索引
- col_level:如果列是多层索引列MultiIndex,则使用此参数;这个参数少用
df3 = pd.melt(df,id_vars='date',value_vars=['type','value'],value_name='observation')
df3
5.wide_to_long
宽面板到长格式。不太灵活,但比melt更方便用户。
使用 stubnames [‘ a’,‘ b’] ,这个函数期望找到一组或多组格式为 A-suffix1,A-suffix2,... ,B-suffix1,b-suffix2的列,... 您可以使用 j 在结果的长格式中指定要调用这个后缀的内容(例如 j =’year’)
假定这些宽变量的每一行都由 i 惟一标识(可以是单个列名或列名列表)
数据框架中的所有其余变量都保持不变。
wide_to_long(
df,
stubnames,
i,
j,
sep: str = "",
suffix: str = "\\d+"
- df:待转换的数据框
- stubnames:宽表中列名相同的存根部分
- i:要用作 id 变量的列
- j:给长格式的“后缀”列设置 columns
- sep:设置要删除的分隔符。例如 columns 为 A-2020,则指定 sep='-' 来删除分隔符。默认为空。
- suffix:通过设置正则表达式取得“后缀”。默认'\d+'表示取得数字后缀。没有数字的“后缀”可以用'\D+'来取得
5.1example
np.random.seed(123)
df = pd.DataFrame({"A1970" : {0 : "a", 1 : "b", 2 : "c"},
"A1980" : {0 : "d", 1 : "e", 2 : "f"},
"B1970" : {0 : 2.5, 1 : 1.2, 2 : .7},
"B1980" : {0 : 3.2, 1 : 1.3, 2 : .1},
"X" : dict(zip(range(3), np.random.randn(3)))
})
df
df['id'] = df.index
pd.wide_to_long(df, ["A", "B"], i='id', j="year")
5.2也可以有非整数作为后缀。
df = pd.DataFrame({
'famid': [1, 1, 1, 2, 2, 2, 3, 3, 3],
'birth': [1, 2, 3, 1, 2, 3, 1, 2, 3],
'ht_one': [2.8, 2.9, 2.2, 2, 1.8, 1.9, 2.2, 2.3, 2.1],
'ht_two': [3.4, 3.8, 2.9, 3.2, 2.8, 2.4, 3.3, 3.4, 2.9]
})
df
l = pd.wide_to_long(df, stubnames='ht', i=['famid', 'birth'], j='age',
sep='_', suffix=r'\w+')
l
6.explode
explode(column, ignore_index=False)
- column:待爆炸的元素
- ignore_index:是否忽略索引;默认是False,保持原来的索引
df = pd.DataFrame({'A': [[0, 1, 2], 'foo', [], [3, 4]],
'B': 1,
'C': [['a', 'b', 'c'], np.nan, [], ['d', 'e']]})
df
df.explode(list('AC'))
6.1小技巧(将字符串转换为列表)
df = pd.DataFrame(columns=['name','hobbies'])
df.name = ['peanut','憨憨']
df.hobbies = ['badminton,study','badminton,research']
df
df['hobbies'] = df['hobbies'].apply(lambda x: x.split(','))
df
df.explode('hobbies')
7.transform
df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar',
'foo', 'bar'],
'B' : ['one', 'one', 'two', 'three',
'two', 'two'],
'C' : [1, 5, 5, 2, 5, 5],
'D' : [2.0, 5., 8., 1., 2., 9.]})
df.groupby('A')['C','D'].transform(lambda x: sum(x))