Python 数据帧:将共享相同列值的多行移位/合并为一行
很抱歉,标题可能会混淆。我将用以下代码和图片更好地描述我的问题 现在我有了一个具有多个列的数据框架。根据前两列对其进行排序,“Route”和“ID”(很抱歉格式化,此处所有行的“Route”值为“100”,而“ID”值为1到3Python 数据帧:将共享相同列值的多行移位/合并为一行,python,pandas,Python,Pandas,很抱歉,标题可能会混淆。我将用以下代码和图片更好地描述我的问题 现在我有了一个具有多个列的数据框架。根据前两列对其进行排序,“Route”和“ID”(很抱歉格式化,此处所有行的“Route”值为“100”,而“ID”值为1到3 df1.head(9) Route ID Year Vol Truck_Vol Truck_% 0 100 1 2017.0 7016 635.0 9.1 1 100 1 2014.0 6835 NaN NaN 2
df1.head(9)
Route ID Year Vol Truck_Vol Truck_%
0 100 1 2017.0 7016 635.0 9.1
1 100 1 2014.0 6835 NaN NaN
2 100 1 2011.0 5959 352.0 5.9
3 100 2 2018.0 15828 NaN NaN
4 100 2 2015.0 13114 2964.0 22.6
5 100 2 2009.0 11844 1280.0 10.8
6 100 3 2016.0 15434 NaN NaN
7 100 3 2013.0 18699 2015.0 10.8
8 100 3 2010.0 15903 NaN NaN
我想要的是
Route ID Year Vol1 Truck_Vol1 Truck_%1 Year2 Vol2 Truck_Vol2 Truck_%2 Year3 Vol3 Truck_Vol3 Truck_%3
0 100 1 2017 7016 635.0 9.1 2014 6835 NaN NaN 2011 5959 352.0 5.9
1 100 2 2018 15828 NaN NaN 2015 13114 2964.0 22.6 2009 11844 1280.0 10.8
2 100 3 2016 15434 NaN NaN 2013 18699 2015.0 10.8 2010 15903 NaN NaN
同样,很抱歉格式太乱。让我试试简化版
输入:
Route ID Year Vol T_%
0 100 1 2017 100 1.0
1 100 1 2014 200 NaN
2 100 1 2011 300 2.0
3 100 2 2018 400 NaN
4 100 2 2015 500 3.0
5 100 2 2009 600 4.0
期望输出:
Route ID Year Vol T_% Year.1 Vol.1 T_%.1 Year.2 Vol.2 T_%.2
0 100 1 2017 100 1.0 2014 200 NaN 2011 300 2
1 100 2 2018 400 NaN 2015 500 3.0 2009 600 4
所以基本上只需移动图中所示的细胞
我被难住了。新生成的列的名称无关紧要
对于当前的数据帧,每个“组”有三行,如代码所示。如果答案可以容纳每个组任意数量的行,那就太好了
谢谢您的时间。melt
+pivot\u表
如果要对这些进行排序:
c = res.columns.str.extract(r'(\d+)')[0].values.astype(int)
res.iloc[:,np.argsort(c)]
你问我为什么使用
cumcount
。下面是v
从上面看的样子:
Route ID variable value
0 100 1 Year 2017.0
1 100 1 Year 2014.0
2 100 1 Year 2011.0
3 100 2 Year 2018.0
4 100 2 Year 2015.0
5 100 2 Year 2009.0
6 100 1 Vol 100.0
7 100 1 Vol 200.0
8 100 1 Vol 300.0
9 100 2 Vol 400.0
10 100 2 Vol 500.0
11 100 2 Vol 600.0
12 100 1 T_% 1.0
13 100 1 T_% NaN
14 100 1 T_% 2.0
15 100 2 T_% NaN
16 100 2 T_% 3.0
17 100 2 T_% 4.0
如果我在这个数据帧上使用pivot\u table
,您将得到如下结果:
variable T_% Vol Year
Route ID
100 1 1.5 200.0 2014.0
2 3.5 500.0 2014.0
显然,您正在丢失这里的数据。
cumcount
是解决方案,因为它将变量
系列转换为以下内容:
Route ID variable value
0 100 1 Year0 2017.0
1 100 1 Year1 2014.0
2 100 1 Year2 2011.0
3 100 2 Year0 2018.0
4 100 2 Year1 2015.0
5 100 2 Year2 2009.0
6 100 1 Vol0 100.0
7 100 1 Vol1 200.0
8 100 1 Vol2 300.0
9 100 2 Vol0 400.0
10 100 2 Vol1 500.0
11 100 2 Vol2 600.0
12 100 1 T_%0 1.0
13 100 1 T_%1 NaN
14 100 1 T_%2 2.0
15 100 2 T_%0 NaN
16 100 2 T_%1 3.0
17 100 2 T_%2 4.0
其中,每个唯一的路线
和ID
melt
+透视表
如果要对这些进行排序:
c = res.columns.str.extract(r'(\d+)')[0].values.astype(int)
res.iloc[:,np.argsort(c)]
你问我为什么使用
cumcount
。下面是v
从上面看的样子:
Route ID variable value
0 100 1 Year 2017.0
1 100 1 Year 2014.0
2 100 1 Year 2011.0
3 100 2 Year 2018.0
4 100 2 Year 2015.0
5 100 2 Year 2009.0
6 100 1 Vol 100.0
7 100 1 Vol 200.0
8 100 1 Vol 300.0
9 100 2 Vol 400.0
10 100 2 Vol 500.0
11 100 2 Vol 600.0
12 100 1 T_% 1.0
13 100 1 T_% NaN
14 100 1 T_% 2.0
15 100 2 T_% NaN
16 100 2 T_% 3.0
17 100 2 T_% 4.0
如果我在这个数据帧上使用pivot\u table
,您将得到如下结果:
variable T_% Vol Year
Route ID
100 1 1.5 200.0 2014.0
2 3.5 500.0 2014.0
显然,您正在丢失这里的数据。
cumcount
是解决方案,因为它将变量
系列转换为以下内容:
Route ID variable value
0 100 1 Year0 2017.0
1 100 1 Year1 2014.0
2 100 1 Year2 2011.0
3 100 2 Year0 2018.0
4 100 2 Year1 2015.0
5 100 2 Year2 2009.0
6 100 1 Vol0 100.0
7 100 1 Vol1 200.0
8 100 1 Vol2 300.0
9 100 2 Vol0 400.0
10 100 2 Vol1 500.0
11 100 2 Vol2 600.0
12 100 1 T_%0 1.0
13 100 1 T_%1 NaN
14 100 1 T_%2 2.0
15 100 2 T_%0 NaN
16 100 2 T_%1 3.0
17 100 2 T_%2 4.0
其中,您有每个唯一的
路由的重复元素计数
和ID
以及groupby
+cumcount
+设置索引
+取消堆栈
df1 = df.assign(cid = df.groupby(['Route', 'ID']).cumcount()).set_index(['Route', 'ID', 'cid']).unstack(-1).sort_index(1,1)
df1.columns = [f'{x}{y}' for x,y in df1.columns]
df1 = df1.reset_index()
输出df1
:
使用
groupby
+cumcount
+set\u index
+unstack
df1 = df.assign(cid = df.groupby(['Route', 'ID']).cumcount()).set_index(['Route', 'ID', 'cid']).unstack(-1).sort_index(1,1)
df1.columns = [f'{x}{y}' for x,y in df1.columns]
df1 = df1.reset_index()
输出df1
:
感谢您的及时回复。这太棒了。但由于我从未使用过cumcount和unstack,您介意解释一下每一步都做了些什么吗?并且代码
[f'{x}{y}在df1.columns中代表x,y
在每个列名的末尾添加0,1,2
?再次感谢!@BowenLiu很抱歉没有提前响应。似乎@user3483203解释了cumcount的原因。由于取消堆栈,我的列只剩下一个多索引,第一级是原始列名,第二级是c中的数字umcount
[f'{x}{y}用于df1.columns中的x,y]
删除列上的多索引,只将cumcount值添加到每个变量名中。@BowenLiu,是的,.sort\u index(1,1)
相当于.sort\u索引(axis=1,level=1)
。指定axis=1
表示我想对列进行排序,通过指定level=1
表示我只想根据该级别中的值(即cumcount变量)对列进行排序。在排序之前,第一级别有值[0,1,2,0,1,2,0,1,2],因此在该级别上进行排序就可以了[0,0,0,1,1,1,2,2]。这不会改变输出DataFrame
中除列的显示顺序以外的任何内容。使用索引很难直接看到值是什么,因此如果执行df1.columns.get_level_值(1)
在第一行代码之后,您可以确切地看到每个级别的值column@BowenLiu是的,它首先对level=1
值进行排序,然后对其余值进行排序(level=0
)。您可以通过在中添加参数sort_remaining=False
来关闭该功能。sort_index
感谢您的及时响应。这太神奇了。但由于我从未使用过cumcount和unstack,您介意解释一下每一步的作用吗?代码是否[f'{x}{y}表示x,y在df1.列中]
在每个列名的末尾添加0,1,2
?再次感谢!@BowenLiu很抱歉没有提前响应。似乎@user3483203解释了cumcount的原因。由于取消堆栈,我的列只剩下一个多索引,第一级是原始列名,第二级是c中的数字umcount
[f'{x}{y}用于df1.columns中的x,y]
删除列上的多索引,只将cumcount值添加到每个变量名中。@BowenLiu,是的,.sort\u index(1,1)
相当于.sort\u索引(axis=1,level=1)
。指定axis=1
表示我想对列进行排序,通过指定level=1
表示我只想根据该级别中的值(即cumcount变量)对列进行排序。在排序之前,第一级别有值[0,1,2,0,1,2,0,1,2],因此在该级别上进行排序就可以了[0,0,0,1,1,1,2,2]。这不会改变输出DataFrame
中除列的显示顺序以外的任何内容。使用索引很难直接看到值是什么,因此如果执行df1.columns.get_level_值(1)
在第一行代码之后,您可以确切地看到每个级别的值column@BowenLiu是的,它首先对level=1
值进行排序,然后对其余值进行排序(level=0
)。您可以通过将参数sort\u remaining=False
添加到。sort\u index
来关闭该功能。非常感谢。我以前从未实际使用过df.melt
,因为我对它的功能感到困惑。您和@