【Pandas学习笔记Task05】:变形

import numpy as np
import pandas as pd

一、长宽表的变形

长表可以理解为某个特征单独作为列索引;而宽表可以以分组的思想去理解,值是其他特征的,但是这个值还包含着某个特征的影响在里面。

1.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
ClassNameSubjectGrade
01San ZhangChinese80
11San ZhangMath75
22Si LiChinese90
32Si LiMath85

目标是将语文和数学分数作为列来展示。其实也就是将subject列的值作为索引然后来将grade进行对应填值。对于长变宽,要有变形后的行索引、需要转到列索引的列,以及行列索引对应的某个特征(Grade)的值。

df.pivot(index='Name', columns='Subject', values='Grade')
SubjectChineseMath
Name
San Zhang8075
Si Li9085
# df.iloc[1, 2] = 'Chinese'
df.pivot(index='Name', columns='Subject', values='Grade')
# 利用pivot要保证pivot后的行列索引对应的值都是唯一的。
SubjectChineseMath
Name
San Zhang8075
Si Li9085
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]})
pivot_multi = df.pivot(index = ['Class','Name'],
                      columns = ['Subject','Examination'],
                      values = ['Grade', 'rank'])
pivot_multi
Graderank
SubjectChineseMathChineseMath
ExaminationMidFinalMidFinalMidFinalMidFinal
ClassName
1San Zhang807590851015207
2Si Li85659288211562

2. pivot_table

pivot_table的使用是用于解决pivot只能对唯一性做变形。这个可以通过聚合将行列组合的多个值变为一个值。

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
NameSubjectGrade
0San ZhangChinese80
1San ZhangChinese90
2San ZhangMath100
3San ZhangMath90
4Si LiChinese70
5Si LiChinese80
6Si LiMath85
7Si LiMath95
df.pivot_table(index = 'Name',
              columns='Subject',
              values = 'Grade',
              aggfunc = 'mean')
# 这里aggfunc代表的是要使用的聚合函数
# 如果有重复值,而且未指定aggfunc,pivot_table默认就取平均
SubjectChineseMath
Name
San Zhang8595
Si Li7590

pivot_table还具有边际汇总,利用margins=True来实现。也就是将每一行再执行一次aggfunc

df.pivot_table(index = 'Name',
              columns='Subject',
              values = 'Grade',
              aggfunc = 'median',
              margins = True)
SubjectChineseMathAll
Name
San Zhang8595.090.0
Si Li7590.082.5
All8092.587.5

总体的汇总为新表中四个元素的平均值.如果是sum或者median,那么sum或者median的是原表的四个值

3.melt

melt可以理解为pivot的相应的逆操作,把宽表转为长表。

df = pd.DataFrame({'Class':[1,2],
                     'Name':['San Zhang', 'Si Li'],
                      'Chinese':[80, 90],
                      'Math':[80, 75]})
df_melted = df.melt(id_vars= ['Class','Name'],
                   value_vars= ['Chinese','Math'],
                   var_name='Subject',
                   value_name='Grade')
df_melted
ClassNameSubjectGrade
01San ZhangChinese80
12Si LiChinese90
21San ZhangMath80
32Si LiMath75
df_unmelted = df_melted.pivot(index = ['Class', 'Name'],
                                 columns='Subject',
                                 values='Grade')
df_unmelted
SubjectChineseMath
ClassName
1San Zhang8080
2Si Li9075
df_unmelted.reset_index().rename_axis(columns={'Subject':''})
ClassNameChineseMath
01San Zhang8080
12Si Li9075

4.wide_to_long

二、索引的变形

1.stack与unstack

将行列索引进行交换,维度会发生变化,这就属于变形。

df = pd.DataFrame(np.ones((4,2)),
                     index =pd.Index([('A', 'cat', 'big'),
                                        ('A', 'dog', 'small'),
                                        ('B', 'cat', 'big'),
                                        ('B', 'dog', 'small')]),
                      columns=['col_1', 'col_2'])
df.unstack()# 默认转化最内层,移动到列索引的最内层
col_1col_2
bigsmallbigsmall
Acat1.0NaN1.0NaN
dogNaN1.0NaN1.0
Bcat1.0NaN1.0NaN
dogNaN1.0NaN1.0
# unstack也支持多层的转化
df.unstack([0,2]) # 这里不支持传切片
col_1col_2
ABAB
bigsmallbigsmallbigsmallbigsmall
cat1.0NaN1.0NaN1.0NaN1.0NaN
dogNaN1.0NaN1.0NaN1.0NaN1.0

三、其他变形函数

1.crosstab

对于crosstab,感觉还是用pivot_table方便。

df = pd.read_csv('data/learn_pandas.csv')
df.pivot_table(index = 'School',
              columns = 'Transfer',
              values = 'Name',
              aggfunc = 'count')
TransferNY
School
Fudan University38.01.0
Peking University28.02.0
Shanghai Jiao Tong University53.0NaN
Tsinghua University62.04.0

2.explode

df_ex = pd.DataFrame({'A': [[1, 2],
                             'my_str',
                             {1, 2},
                             pd.Series([3, 4])],
                          'B': 1})
df_ex
AB
0[1, 2]1
1my_str1
2{1, 2}1
30 3 1 4 dtype: int641
df_ex.explode('A') # 对某一列纵向展开
AB
011
021
1my_str1
2{1, 2}1
331
341
pd.get_dummies(df.Grade).head()# 这是一个DataFrame,将某列的唯一值作为列索引,值0与1代表特征
FreshmanJuniorSeniorSophomore
01000
11000
20010
30001
40001

四、练习

1.EX1:美国非法药物数据集

df = pd.read_csv('data/drugs.csv').sort_values(['State','COUNTY','SubstanceName'],ignore_index=True)
df.head()
YYYYStateCOUNTYSubstanceNameDrugReports
02011KYADAIRBuprenorphine3
12012KYADAIRBuprenorphine5
22013KYADAIRBuprenorphine4
32014KYADAIRBuprenorphine27
42015KYADAIRBuprenorphine5
res = df.pivot(index=['State','COUNTY','SubstanceName'],
              columns='YYYY',
              values='DrugReports')
res = res.reset_index().rename_axis(columns={'YYYY':''})
res.head()

转换数据格式这里直接想到前面的pivot方法。(虽然想到了,但是应用起来还是不熟练,不得不返回去再看一遍)。而且还包含着要去对索引层名字的修改与重置。

StateCOUNTYSubstanceName20102011201220132014201520162017
0KYADAIRBuprenorphineNaN3.05.04.027.05.07.010.0
1KYADAIRCodeineNaNNaN1.0NaNNaNNaNNaN1.0
2KYADAIRFentanylNaNNaN1.0NaNNaNNaNNaNNaN
3KYADAIRHeroinNaNNaN1.02.0NaN1.0NaN2.0
4KYADAIRHydrocodone6.09.010.010.09.07.011.03.0
res_melted = res.melt(id_vars = ['State','COUNTY','SubstanceName'],
                         value_vars = res.columns[-8:],
                         var_name = 'YYYY',
                         value_name = 'DrugReports').dropna(
                         subset=['DrugReports'])
res_melted.head()
StateCOUNTYSubstanceNameYYYYDrugReports
4KYADAIRHydrocodone20106.0
6KYADAIRMethadone20101.0
13KYALLENHydrocodone201010.0
15KYALLENMethadone20104.0
17KYALLENOxycodone201015.0
res_melted = res_melted[df.columns].sort_values([
                  'State','COUNTY','SubstanceName'],ignore_index=True
                  ).astype({'YYYY':'int64', 'DrugReports':'int64'})
res_melted.head()
YYYYStateCOUNTYSubstanceNameDrugReports
02011KYADAIRBuprenorphine3
12012KYADAIRBuprenorphine5
22013KYADAIRBuprenorphine4
32014KYADAIRBuprenorphine27
42015KYADAIRBuprenorphine5
恢复的过程也就是对melt方法的应用。(这里对melt的参数运用还没有理解到位,于是就只能照猫画虎将实例的参数设置对应着搬过来用)。因为第1问的DrugReports格式被改为了float64,所以答案用astype方法将类型重置为int64.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值