如何将pandas数据框的索引转换为列

814
如何将数据框的索引转换为列?
例如:
        gi       ptt_loc
 0  384444683      593  
 1  384444684      594 
 2  384444686      596  

    index1    gi       ptt_loc
 0  0     384444683      593  
 1  1     384444684      594 
 2  2     384444686      596  

2
如果在groupby之后,你可以通过as_index完全避免它。 - Josiah Yoder
10个回答

1332

两者之一:

df['index1'] = df.index

或者.reset_index

df = df.reset_index()

如果您有一个包含3级索引的多层级框架,例如:
>>> df
                       val
tick       tag obs        
2016-02-26 C   2    0.0139
2016-02-27 A   2    0.5577
2016-02-28 C   6    0.0303

如果你想将索引中的第一(tick)和第三个(obs)级别转换为列,可以执行以下操作:
>>> df.reset_index(level=['tick', 'obs'])
          tick  obs     val
tag                        
C   2016-02-26    2  0.0139
A   2016-02-27    2  0.5577
C   2016-02-28    6  0.0303

4
你能在刚刚添加到数据框中的列上建立索引,使它成为一个真正的列和索引吗?请注意不要改变原来的意思。 - bretcj7
5
如果想要转换整个多重索引,只需使用 df.reset_index() 命令,该命令将索引的全部内容移动到列中(每个级别对应一列),并创建一个从0到len(df)-1的整数索引。 - BallpointBen
我有一个Categoricalindex,其中包含每个项目的元组,并且我想从元组中仅创建一个新列。 有没有关于如何从索引中提取一个项目的想法? - AdamRedwine
8
对某一列进行赋值操作,例如 df['index1'] = df.index,会返回警告信息:"A value is trying to be set on a copy of a slice from a DataFrame." 请改用 df.assign() 函数进行赋值操作,具体使用方法如下: - John Mark
我之前也遇到过类似的问题,尝试了这个解决方案却没有任何结果。不过@venti提供的解决方案正是我所需要的。 - Jorge Mendoza Ruiz
这也适用于pandas.Series - 并将Series转换为数据帧。 - DryLabRebel

68

rename_axis + reset_index

你可以先将索引重命名为所需的标签,然后提升到系列:

df = df.rename_axis('index1').reset_index()

print(df)

   index1         gi  ptt_loc
0       0  384444683      593
1       1  384444684      594
2       2  384444686      596

这也适用于 MultiIndex 数据框:

print(df)
#                        val
# tick       tag obs        
# 2016-02-26 C   2    0.0139
# 2016-02-27 A   2    0.5577
# 2016-02-28 C   6    0.0303

df = df.rename_axis(['index1', 'index2', 'index3']).reset_index()

print(df)

       index1 index2  index3     val
0  2016-02-26      C       2  0.0139
1  2016-02-27      A       2  0.5577
2  2016-02-28      C       6  0.0303

54

为了提供更多的明确性,让我们看一下一个在其索引中具有两个级别(MultiIndex)的DataFrame。

index = pd.MultiIndex.from_product([['TX', 'FL', 'CA'], 
                                    ['North', 'South']], 
                                   names=['State', 'Direction'])

df = pd.DataFrame(index=index, 
                  data=np.random.randint(0, 10, (6,4)), 
                  columns=list('abcd'))

enter image description here

调用默认参数的reset_index方法,将所有索引级别转换为列,并使用简单的RangeIndex作为新索引。

df.reset_index()

这里输入图片描述

使用level参数来控制将哪些索引级别转换为列。如果可能的话,使用级别名称,因为更加明确。如果没有级别名称,可以通过其整数位置来引用每个级别,这从外部开始从0开始。您可以在此处使用标量值或要重置的所有索引的列表。

df.reset_index(level='State') # same as df.reset_index(level=0)

输入图片说明

如果极少数情况下您想保留索引并将其转换为列,可以执行以下操作:

# for a single level
df.assign(State=df.index.get_level_values('State'))

# for all levels
df.assign(**df.index.to_frame())

43

对于MultiIndex,您可以使用以下方法提取其子索引:

df['si_name'] = R.index.get_level_values('si_name') 

其中 si_name 是子指数的名称。


15

如果你想使用 reset_index 方法并保留原有的索引,你应该使用:

df.reset_index().set_index('index', drop=False)

或在原地进行更改:

df.reset_index(inplace=True)
df.set_index('index', drop=False, inplace=True)

例如:
print(df)
          gi  ptt_loc
0  384444683      593
4  384444684      594
9  384444686      596

print(df.reset_index())
   index         gi  ptt_loc
0      0  384444683      593
1      4  384444684      594
2      9  384444686      596

print(df.reset_index().set_index('index', drop=False))
       index         gi  ptt_loc
index
0          0  384444683      593
4          4  384444684      594
9          9  384444686      596

如果您想取消索引标签,可以使用以下方法:

df2 = df.reset_index().set_index('index', drop=False)
df2.index.name = None
print(df2)
   index         gi  ptt_loc
0      0  384444683      593
4      4  384444684      594
9      9  384444686      596

13

这应该能解决问题(如果没有多级索引) -

df.reset_index().rename({'index':'index1'}, axis = 'columns')

Code Result

当然,在rename函数的参数中设置 inplace=True ,如果您不想将其分配给新变量。


5
df1 = pd.DataFrame({"gi":[232,66,34,43],"ptt":[342,56,662,123]})
p = df1.index.values
df1.insert( 0, column="new",value = p)
df1

    new     gi     ptt
0    0      232    342
1    1      66     56 
2    2      34     662
3    3      43     123

5
我建议增加一些讨论,解释为什么你认为这个答案比现有的答案更好。 - dmcgrandle
这种使用插入方法的方法有助于将列插入到DataFrame的左端(第一列)位置,而不是在右端(最后一列)插入列。 因此,对于某些情况而言,它可能非常有用。 最好通过答案来解释它。 - fillo

3
为了保留索引(已转换为列)作为索引,请使用 to_frame()join() 的组合。特别是,这不会像赋值一样产生 SettingWithCopyWarning
df = df.index.to_frame(name='A').join(df)

res1

这对于MultiIndex也适用。

df = df.index.to_frame(name=['A', 'B']).join(df)

此外,正如 Quinten所提到的那样,自pandas 1.5.0以来,rename_axis + reset_index(或reset_index + rename)语法已经过时。您可以直接将names=作为参数传递给reset_index()。即使传递了allow_duplicates=True(虽然具有重复列标签是极不可取的),也允许重复的列名。
df = df.reset_index(names=['A', 'B'])

res2


2
在最新版本的pandas 1.5.0中,您可以使用函数reset_index,并使用新参数names指定要赋予索引列的名称列表。以下是一个具有一个索引列的可重现示例:
import pandas as pd

df = pd.DataFrame({"gi":[232,66,34,43],"ptt":[342,56,662,123]})

    gi  ptt
0  232  342
1   66   56
2   34  662
3   43  123

df.reset_index(names=['new'])

输出:

   new   gi  ptt
0    0  232  342
1    1   66   56
2    2   34  662
3    3   43  123

这也可以很容易地应用于MultiIndex。只需创建您想要的名称列表即可。


2

我通常是这样做的:

df = df.assign(index1=df.index)

这将在现有列的右侧添加新列,可能会有些奇怪。我发现另一种选择是使用 insert,例如 df.insert(0, 'id', df.index),其中 0 是列的索引。 - basquiatraphaeu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接