Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 数据帧:将共享相同列值的多行移位/合并为一行_Python_Pandas - Fatal编程技术网

Python 数据帧:将共享相同列值的多行移位/合并为一行

Python 数据帧:将共享相同列值的多行移位/合并为一行,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

很抱歉,标题可能会混淆。我将用以下代码和图片更好地描述我的问题

现在我有了一个具有多个列的数据框架。根据前两列对其进行排序,“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   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
,因为我对它的功能感到困惑。您和@