Python 如何将熊猫中重复编号的列转换为单数的非编号列?

Python 如何将熊猫中重复编号的列转换为单数的非编号列?,python,python-3.x,pandas,dataframe,Python,Python 3.x,Pandas,Dataframe,很抱歉这个可能很糟糕的标题,但我自己很难理解如何描述这个。我有一个数据集,当读入pandas数据框时,其形状大致如下: import pandas as pd import numpy as np df_all = pd.DataFrame(np.random.randn(2, 6), columns=["0_X", "0_Y", "1_X", "1_Y", "2_X", "2_Y"]) 0_X 0_Y 1_X 1_Y 2_X 2

很抱歉这个可能很糟糕的标题,但我自己很难理解如何描述这个。我有一个数据集,当读入pandas数据框时,其形状大致如下:

import pandas as pd 
import numpy as np
df_all = pd.DataFrame(np.random.randn(2, 6), columns=["0_X", "0_Y", "1_X", "1_Y", "2_X", "2_Y"])
  0_X       0_Y       1_X       1_Y       2_X       2_Y
0 1.470289  0.588573  1.303684  1.374806  1.025082  0.316623
1 0.426527  2.036558  0.100993  2.485025  0.350100  0.603069
具有相同编号的每对列表示对象在给定时间戳的X、Y位置。每行代表一个新的时间戳。我想做的是将此数据帧转换为如下内容:

   Time   ObjectId   X         Y 
0  0      0          1.470289  0.588573  
1  0      1          1.303684  1.374806  
2  0      2          1.025082  0.316623
3  1      0          0.426527  2.036558  
4  1      1          0.100993  2.485025  
5  1      2          0.350100  0.603069
现在,我知道我可以从列名中提取相关信息,然后像这样重复:

obj_ids = []
for each_column in list(df_all.columns):
  obj_id = each_column.split("_")[0]
  if obj_id not in obj_ids:
    obj_ids.append(obj_id)

df_all_rotated = pd.DataFrame()
df_all_rotated["ObjectID"] = obj_ids 
df_all_rotated = pd.concat([df_all_rotated ] * len(df_all.index), ignore_index=True)
这产生了接近我想要的第一部分的东西:

      ObjectId   
0     0
1     1
2     2
3     0
4     1
5     2
但不幸的是,我在思考如何将X,Y点移动到数据帧中的正确位置时陷入了困境。我知道可以通过在整个数据帧上循环并将每个数据帧单元设置为其各自的值来实现这一点,但这些方法似乎效率低下,特别是考虑到数据集将以MBs的形式存储信息,并且我在Pandas中使用类似C的循环方法时有很差的运行经验

简单的答案是更改数据集,但遗憾的是,我无法控制数据集的生成方式:


感谢您的帮助!如果这是转载,我很抱歉。

我们首先将列索引转换为a,然后将第一级转换为列。最后,我们将介绍新的专栏:

df = pd.DataFrame(np.random.randn(2, 6), columns=["0_X", "0_Y", "1_X", "1_Y", "2_X", "2_Y"])

df.columns = pd.MultiIndex.from_tuples([c.split('_') for c in df.columns])
df.stack(0).reset_index().rename(columns={'level_0': 'Time', 'level_1': 'ObjectId'})
   Time ObjectId         X         Y
0     0        0  0.862742 -1.642483
1     0        1  0.786022 -0.661986
2     0        2  0.044130  1.054564
3     1        0 -1.415127 -1.197613
4     1        1  0.530939  1.238403
5     1        2  0.495760  0.101748
编辑: 正如下面sammywemmy所评论的,您可以将第一行简化为

df.columns = df.columns.str.split('_', expand=True)
这是宽到长的


假设X和Y的数量相同安全吗?我觉得我以前也看到过类似的问题,也许只需稍加搜索就可以找到它,因为我可以在mpandas中找到它,因为将expand设置为True的string split将为您提供一个多索引。不再需要遍历列并调用pd。multiindex@sammywemmy:非常感谢,我不知道。将其包含在答案中。这很有效!非常感谢,我很感激。标记为已回答。对于遇到这个问题的其他人,请注意df.stack返回一个数据帧,因此您需要通过说df=df.stack之类的话来捕获更新后的数据帧。我一直在努力让它工作,谢谢!这是最好的答案
df_all.columns=df_all.columns.str.split('_').map(lambda x : ''.join(x[::-1]))

df=pd.wide_to_long(df_all.rename_axis('Time').reset_index(),['X','Y'],i='Time',j='ObjectId',suffix='\\w+').reset_index()
df
Out[89]: 
   Time  ObjectId         X         Y
0     0         0 -0.121748  0.146057
1     1         0  1.883143  0.088054
2     0         1  0.841091 -1.034432
3     1         1  0.444028 -0.711991
4     0         2 -0.677578  1.401241
5     1         2 -0.424676 -0.933622