Pandas学习-Task05

第五章 变形

Datawhale开源内容链接: https://datawhalechina.github.io/joyful-pandas/build/html/%E7%9B%AE%E5%BD%95/ch5.html

1、长宽表介绍。

这里的长与宽都是针对于某一个特征来说的。比如,将性别作为列名且该列的元素都是性别的值时,这就称为关于性别的长表。但将性别的unique值作为列名且该列元素是其他索引的值时,则称为关于性别的宽表
在这里插入图片描述
以上的长表与宽表,从信息角度上看,是等价的。但在呈现的方式上有所不同。所以本章节主要学习这两种表之间的变换–变形函数

2、长表变宽表—pivot。

df = pd.DataFrame({'Class':[1,1,2,2],
                  'Name':['San Zhang', 'San Zhang', 'Si Li', 'Si Li'],
                  'Subject':['Chinese','Math','Chinese','Math'],
                  'Grade':[80,75,90,85]})
df
df.pivot(index='Name', columns='Subject', values='Grade')

在这里插入图片描述
变形过程图解
在这里插入图片描述
⚠️注意:利用pivot进行变形操作需要满足唯一性的要求,即由于在新表中的行列索引对应了唯一的value,因此index与columns对应的两个列的组合必须唯一。

将pivot的三个参数设置为列表(这就意味着会返回多级索引)。
df = pd.DataFrame({'Class':[1, 1, 2, 2, 1, 1, 2, 2],
                  'Name':['San Zhang', 'San Zhang', 'Si Li', 'Si Li', 'San Zhang', 'San Zhang', 'Si Li', 'Si Li'],
                  'Examination':['Mid', 'Final', 'Mid', 'Final', 'Mid', 'Final', 'Mid', 'Final'],
                  'Subject':['Chinese', 'Chinese', 'Chinese', 'Chinese', 'Math', 'Math', 'Math', 'Math'],
                  'Grade':[80, 75, 85, 65, 90, 85, 92, 88],
                  'rank':[10, 15, 21, 15, 20, 7, 6, 2]})
df

在这里插入图片描述
【题目】
将测试类型和科目联合组成的四个类别(期中语文、期末语文、期中数学、期末数学)转到列索引,并且同时统计成绩和排名。

在这里插入图片描述
【思考】
从上图可以看出,我最初是将Examination作为了外层行索引,返回的值中关于Mid的两个值并没有合并,这是因为原数据中Examination就是交叉着排列的,但Subject是顺序排列的。所以将Subject设置为外层索引的时候,就可以自动折叠合并啦。

pivot_table可以通过聚合操作将相同行列组合对应的多个值变为一个值。
df = pd.DataFrame({'Name':['San Zhang', 'San Zhang', 'San Zhang', 'San Zhang', 
                           'Si Li', 'Si Li', 'Si Li', 'Si Li'],
                  'Subject':['Chinese', 'Chinese', 'Math', 'Math', 'Chinese', 'Chinese', 'Math', 'Math'],
                  'Grade':[80,90,100,90,70,80,85,95]})
df
## 张三和李四都参加了两次语文考试和数学考试,最后的成绩是两次考试分数的平均值。
df.pivot_table(index = 'Name',
              columns = 'Subject',
              values = 'Grade',
              aggfunc = 'mean')

在这里插入图片描述

3、宽表变长表。

df = pd.DataFrame({'Class':[1,2],
                  'Name':['San Zhang', 'Si Li'],
                  'Chinese':[80, 90],
                  'Math':[80,75]})
df
## 将subject以列索引的形式存储,将其压缩至一个列中
df_melted = df.melt(id_vars = ['Class','Name'],
                   value_vars = ['Chinese', 'Math'],
                   var_name = 'Subject',
                   value_name = 'Grade')
df_melted

在这里插入图片描述
变形过程图解
在这里插入图片描述

wide_to_long

与melt只能压缩同一层含义的列元素不同的是,wide_to_long可以将包含交叉特征的索引分开,只压缩其中一部分特征。

df = pd.DataFrame({'Class':[1,2],'Name':['San Zhang', 'Si Li'],
                  'Chinese_Mid':[80, 75], 'Math_Mid': [90, 85],
                  'Chinese_Final':[80, 75], 'Math_Final': [90, 85]})
df
pd.wide_to_long(df,
               stubnames=['Chinese','Math'],
               i = ['Class', 'Name'],
               j = 'Examination',
               sep = '_',
               suffix = '.+')

【题目】
将Grade扩充为语文和数学两列,只把期中期末压缩:
在这里插入图片描述

变形过程图解
在这里插入图片描述
【补充】
修改列名的两种方法:
1、直接替换之前的全部列名:

df.columns = ['A','B']

2、只替换对应列的列名:

res.rename(columns={'Subjec':'Subject'},inplace=True)

注意:需要添加inplace=True,否则只是暂时修改,并没有改DataFrame里面的值。

将pivot多列操作的结果,利用wide_to_long函数转换为原来的形态。
df = pd.DataFrame({'Class':[1, 1, 2, 2, 1, 1, 2, 2],
                  'Name':['San Zhang', 'San Zhang', 'Si Li', 'Si Li', 'San Zhang', 'San Zhang', 'Si Li', 'Si Li'],
                  'Examination':['Mid', 'Final', 'Mid', 'Final', 'Mid', 'Final', 'Mid', 'Final'],
                  'Subject':['Chinese', 'Chinese', 'Chinese', 'Chinese', 'Math', 'Math', 'Math', 'Math'],
                  'Grade':[80, 75, 85, 65, 90, 85, 92, 88],
                  'rank':[10, 15, 21, 15, 20, 7, 6, 2]})
df
pivot_multi = df.pivot(index=['Class','Name'], columns=['Subject', 'Examination'], values=['Grade','rank'])
pivot_multi
res = pivot_multi.copy()
res

在这里插入图片描述

res.columns = res.columns.map(lambda x:'_'.join(x))
res = res.reset_index()
res = pd.wide_to_long(res, stubnames=['Grade','rank'],
                     i = ['Class', 'Name'],
                     j = 'Subject_Examination',
                     sep = '_',
                     suffix = '.+')
res = res.reset_index()
res[['Subject','Examination']] = res[
    'Subject_Examination'].str.split('_', expand=True)
res = res[['Class','Name','Examination','Subject','Grade','rank']].sort_values('Subject')
res = res.reset_index(drop=True)
res

在这里插入图片描述

4、索引的变形

unstack函数的作用是:把行索引转为列索引。
stack函数的作用是:把列索引的层压入行索引。

【总结】
上面介绍的所有函数中,除了带有聚合效果的pivot_table以外,其他函数在变性前后并不会带来values个数的变化,只是这些值在呈现的形式上发生了变化。
values的个数是否产生了变化,这是分组聚合与变形函数的最大区别。

5、其他变形函数

crosstab可以统计元素组合出现的频数,即count操作。
explode能够将某一列的元素进行纵向的展开,被展开的单元格必须存储list, turple, Series, np.ndarray中的一种类型。
get_dummies的作用是把类别特征转为指示变量。例如,对年级一列转为指示变量,属于某一个年级的对应位置标记为1,否则为0。这个函数在特征构建时经常使用。

练习题1: 美国非法药物数据集

1、将数据转化为下面图的格式。

【我的解答】

这个没什么难度,其实就是把YYYY这一列的值转换为列索引。直接使用pivot即可,不过我最初是把重置索引和重命名分开来做的,但是后面的操作还是会基于原始的pivot,所以就把它们写为一句了。

df = pd.read_csv('joyful-pandas-master/data/drugs.csv')
pivot1 = df.pivot(index=['State','COUNTY','SubstanceName'], columns='YYYY', values='DrugReports').reset_index().rename_axis(columns={'YYYY':''})
pivot1

在这里插入图片描述
2、将第1问的结果恢复为原表。

【我的解答】

df_melted = pivot1.melt(id_vars = ['State','COUNTY','SubstanceName'],
                   value_vars = pivot1.columns[-8:],
                   var_name = 'YYYY',
                   value_name = 'DrugReports')
df_melted.dropna(subset=['DrugReports'])

我最初没有使用dropna去掉空值,导致保留了很多不必要的行。

3、按 State 分别统计每年的报告数量总和,其中 State, YYYY 分别为列索引和行索引,要求分别使用 pivot_table 函数与 groupby+unstack 两种不同的策略实现,并体会它们之间的联系。

pivot_table:

res = df.pivot_table(index='YYYY', columns='State',values='DrugReports', aggfunc='sum')
res

groupby+unstack:

res = df.groupby(['State', 'YYYY'])['DrugReports'].sum().to_frame().unstack(0).droplevel(0,axis=1)
res
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值