看过来
《pandas 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
今天我们将一个 Series 序列数据转为 DataFrame结构。我们将用么 pd.cut()
对数据进行分箱,也会用到 NumPy 的 np.reshape()
对阵列数据进行变形。接下来我们看看具体的需求,再分析一下解决思路,最后用代码实现它。
原数据如下,这是一个 Series,从 1 到 24 的等差数列:
import pandas as pd
import numpy as np
ser = pd.Series(range(1, 25))
ser
'''
0 1
1 2
2 3
...
22 23
23 24
dtype: int64
'''
需要转为以下形式。对数列整体等分划为三部分,每个部分有两列,前四个在第一列,后四个在第二列,同时对每份数据指定了同名的索引标签。
# 转为以下数据
'''
A B
y
1 A 1 5
B 2 6
C 3 7
D 4 8
2 A 9 13
B 10 14
C 11 15
D 12 16
3 A 17 21
B 18 22
C 19 23
D 20 24
'''
为了方便后续操作,可以将数据先转为 DataFrame,这样我们就可以新增加辅助列了。由于要对现有数据等份划分,我们可以我是利用 pd.cut()
数据分箱来完成,对它指定箱子数量,可以帮助我们进行平均划分,为了方便识别我们在分箱后对每个箱子的标签进行指定。
接下来,按箱子的标签进行分组,每个组就是要分在一起的数据,我们写一个函数对这些数据进行处理,拼接成想要的数据格式。
处理分组的函数可以这样设计,由于它接收的数据只有一列,我们将它 用 NumPy 的 np.reshape()
进行形状变化,变化后构造为 DataFrame,同时给出列和行的标签值。
我们将上述的思路进行代码实现。先将 Series 转为 DataFrame,列名为 x,用 pd.cut()
增加 y 辅助列,用来标识要分在一起的值:
(
ser.to_frame('x') # 将 Series 转为 DataFrame
# 增加标识,划分为三组
.assign(y=pd.cut(ser.index, bins=3, labels=[*'123']))
)
'''
x y
0 1 1
1 2 1
2 3 1
...
22 23 3
23 24 3
'''
接下来写分组处理函数:
def reshape_as_df(grp: pd.DataFrame):
data = np.reshape(grp.x.to_numpy(), [4, 2], order='F')
return pd.DataFrame(data,
index=[*'ABCD'],
columns=[*'AB'])
grp 参数是先个分组的 DataFrame 数据,它只有一列 x,索引为 y,先将 x 转为 array 类型传入 np.reshape()
进行形状的变化,这里我们变为 4x2(四行两列),用 order 指定 Fortran-like 索引顺序,这样数据变形的排序就是按列方向的。
最后将变形后的数据构造为 DataFrame,指定行列返回。
最后分组并应用这个函数,最终代码为:
def reshape_as_df(grp: pd.DataFrame):
data = np.reshape(grp.x.to_numpy(), [4, 2], order='F')
return pd.DataFrame(data,
index=[*'ABCD'],
columns=[*'AB'])
# 最终代码
(
ser.to_frame('x') # 将 Series 转为 DataFrame
# 增加标识,划分为三组
.assign(y=pd.cut(ser.index, bins=3, labels=[*'123']))
.groupby('y') # 分组
.apply(reshape_as_df) # 应用函数
)
'''
A B
y
1 A 1 5
B 2 6
C 3 7
D 4 8
2 A 9 13
B 10 14
C 11 15
D 12 16
3 A 17 21
B 18 22
C 19 23
D 20 24
'''
这样我们就完成了需求。
(完)
更新时间:Aug. 18, 2024, 3:55 p.m. 标签:pandas python numpy 数据变形