Python 使用列名将列聚合到行

Python 使用列名将列聚合到行,python,pandas,Python,Pandas,我有以下数据帧 df = pd.DataFrame({'ID':[1,2,3],'Q8_4_1':[1,2,3], 'Q8_5_1':[2,5,7],'Q8_4_2':[6,7,8], 'Q8_5_2':[9,10,11]}) 这些列仅代表不同文件的相同变量。因此,结构如下Q8_4_文件1、Q8_4_文件2等。我希望将数据帧转换为以下表示形式: 目前,我正在运行一个不太理想的解决方案,其中包括对列索引进行硬编码,并按文件id拆分数据帧,如下所示: df1 = df.iloc[:,:3] df1

我有以下数据帧

df = pd.DataFrame({'ID':[1,2,3],'Q8_4_1':[1,2,3], 'Q8_5_1':[2,5,7],'Q8_4_2':[6,7,8], 'Q8_5_2':[9,10,11]})
这些列仅代表不同文件的相同变量。因此,结构如下Q8_4_文件1、Q8_4_文件2等。我希望将数据帧转换为以下表示形式:

目前,我正在运行一个不太理想的解决方案,其中包括对列索引进行硬编码,并按文件id拆分数据帧,如下所示:

df1 = df.iloc[:,:3]
df1.columns = ["ID","Q8_4","Q_5"]
df1["File_ID"] = 1

df2 = df.iloc[:,3:]
df2["ID"] = df["ID"]
df2.columns = ["ID","Q8_4","Q_5"]
df2["File_ID"] = 2

pd.concat([df1,df2],axis=0)
是否有任何pandas功能可以帮助我在可扩展级别上实现这一点?

使用axis=1和concat上的groupby的另一种方式:

# Step 0: create the dataframe
df = pd.DataFrame({'ID':[1,2,3],'Q8_4_1':[1,2,3], 'Q8_5_1':[2,5,7],'Q8_4_2':[6,7,8], 'Q8_5_2':[9,10,11]}).set_index("ID")

# Step 1: create a function to split the column names
def split_col(s): 
    comp = s.split("_") 
    return "_".join(comp[:-1]), comp[-1] 

# Step 2: create a new index for the columns and update it
df.columns = pd.MultiIndex.from_tuples(list(map(split_col, df.columns)))

# Step 3: stack based on level #1
df = df.stack(level=1)

# Step 4: nope, that's it
在轴=1和concat上使用groupby的另一种方法:


使用枢轴选项时要小心。如果使用df.columns重命名,则序列可能会更改。尝试使用df.renamecolumns=Dict。在本例中,实际上是将Q8_5_2与Q8_4_1合并。我认为这不是你所期望的。使用枢轴选项要小心。如果使用df.columns重命名,则序列可能会更改。尝试使用df.renamecolumns=Dict。在本例中,实际上是将Q8_5_2与Q8_4_1合并。我想这不是你所期望的。看起来很棒,谢谢!将df=df.reset_index df.renamecolumns={level_1:File_ID},inplace=True添加到您的解决方案中,为我提供了所需的输出,看起来很棒,谢谢!将df=df.reset\u index df.renamecolumns={level_1:File\u ID},inplace=True添加到您的解决方案中,得到了所需的输出
col=df.columns[1:].str.rsplit('_',1).str[0]
final=pd.concat([g.stack().droplevel(1) for _,g in 
               df.set_index('ID').groupby(col,axis=1)],axis=1,keys=col).reset_index()
final=final.assign(File_ID=final.groupby('ID').cumcount()+1)
print(final)
   ID  Q8_4  Q8_5  File_ID
0   1     1     2        1
1   1     6     9        2
2   2     2     5        1
3   2     7    10        2
4   3     3     7        1
5   3     8    11        2