最新消息:XAMPP默认安装之后是很不安全的,我们只需要点击左方菜单的 "安全"选项,按照向导操作即可完成安全设置。

pandas 长宽表转换

XAMPP案例 admin 98浏览 0评论

pandas 长宽表转换

宽变长

起因:生物统计学考试

考试时拿到的excel如下:

drh29

使用pandas读取。

data = pd.read_excel('考试数据.xlsx', sheet_name=2, skiprows=0)
.head()

out:

    饲料A    饲料B
0    3.08    3.43
1    2.73    3.04
2    3.03    3.37
3    2.95    3.29
4    2.21    2.46

乍一看数据没什么问题。然而,如果不是已经看过excel,我们可能就会忽略饲料B最后一行的NaN

data.tail(1)

out:

    饲料A    饲料B
9    2.89    NaN

按照要求,现在要对饲料A和饲料B的数据做一个boxplot。

选择使用seaborn模块的boxplot函数。

该函数至少需要xy,以及提供数据的datax提供x轴分类,y提供y轴数据,左看右看,这个数据是不能直接送入函数的。

我们希望得到的数据是这样的。

drh029

这种变化,我们称之为长宽表转变。顾名思义,就是从宽表转变为长表,或者长表转变成宽表。长表的特点是同类列名展开,而宽表是同类列名合并。在这里,饲料A与饲料B就属于同类列名,

此时,当然可以直接修改excel,搞成左侧是变量,右侧是值的样子,然而这并不优雅。

在pandas中,我们可以使用melt函数完成宽变长。

data.melt().head()

out:

    variable    value
0    饲料A    3.08
1    饲料A    2.73
2    饲料A    3.03
3    饲料A    2.95
4    饲料A    2.21

默认情况下,melt将所有列名变成variable,其值为value。在这里是合适的。

更准确的写法如下:

data.melt(value_vars=['饲料A','饲料B'], var_name='饲料', value_name='值').head()

out:

    饲料    值
0    饲料A    3.08
1    饲料A    2.73
2    饲料A    3.03
3    饲料A    2.95
4    饲料A    2.21

melt还有一个参数是id_vars,指定后可以出现在结果中。为了示例,我们加入index作为id。

data = pd.read_excel('考试数据.xlsx', sheet_name=2, skiprows=0)
data.reset_index(inplace = True)
data.head()

out:

    index    饲料A    饲料B
0    0    3.08    3.43
1    1    2.73    3.04
2    2    3.03    3.37
3    3    2.95    3.29
4    4    2.21    2.46

然后melt

data.melt(id_vars='index', value_vars=['饲料A','饲料B'], var_name='饲料', value_name='值').head()

out:

    index    饲料    值
0    0    饲料A    3.08
1    1    饲料A    2.73
2    2    饲料A    3.03
3    3    饲料A    2.95
4    4    饲料A    2.21

删除NaN数据行并画图。画图时一般需要长表,就是因为同类多列名其数据点个数可能不同,易出问题。

plot_data = data.melt(value_vars=['饲料A','饲料B'], var_name='饲料', value_name='值') 
plot_data = plot_data.dropna()
import seaborn as sns
sns.boxplot(x = '饲料', y = '值',data = plot_data)

长变宽

如果我们拿到的是长数据,需要转变成宽数据。

plot_data.head()

out:

    饲料    值
0    饲料A    3.08
1    饲料A    2.73
2    饲料A    3.03
3    饲料A    2.95
4    饲料A    2.21

可以使用pivot

plot_data.pivot(columns='饲料', values='值')

out:

饲料    饲料A    饲料B
0    3.08    NaN
1    2.73    NaN
2    3.03    NaN
3    2.95    NaN
4    2.21    NaN
...
14    NaN    2.46
15    NaN    3.37
16    NaN    3.19
17    NaN    2.89
18    NaN    3.49

在长变宽时,因为plot_data中并没有饲料A和饲料B的配对信息,所以他们不会出现在同一行。

保留index后,该配对信息存在,因此会出现在同一行。

plot_data = data.melt(id_vars = 'index', value_vars=['饲料A','饲料B'], var_name='饲料', value_name='值')
plot_data = plot_data.dropna()
plot_data.pivot(index = 'index', columns='饲料',values='值').tail()

out:

饲料    饲料A    饲料B
index        
5    3.03    3.37
6    2.86    3.19
7    3.13    2.89
8    2.59    3.49
9    2.89    NaN

最后一行饲料B没有数据所以为NaN

长变宽时的聚合

pivot有一个类似函数是pivot_table,可以实现在长变宽时的聚合功能。

plot_data.pivot_table(columns='饲料', values='值', aggfunc={np.sum, np.mean})

out:

饲料    饲料A    饲料B
mean    2.85    3.17
sum    28.50    28.53

在数据处理方面很实用。

宽变长进阶版

在宽变长方面,pandas提供了一个数据要求更高但是更用户友好的函数,wide_to_long

data.head()

out:

    index    饲料A    饲料B
0    0    3.08    3.43
1    1    2.73    3.04
2    2    3.03    3.37
3    3    2.95    3.29
4    4    2.21    2.46

按照要求,同类的列名需要有相同的开头,此时数据已经满足条件。

pd.wide_to_long(data, ["饲料"], i="index", j="类型", suffix=r'\w+')

out:

饲料
index    类型    
0    A    3.08
1    A    2.73
2    A    3.03
3    A    2.95
4    A    2.21

j是识别出的suffix组成列的列名。suffix在不指定时会运行失败,因为函数在默认情况下只能识别数字后缀。

更详细的用法,请参考wide_to_long API[1]

转载请注明:XAMPP中文组官网 » pandas 长宽表转换