我该如何在pandas数据框中更改单个索引值?

98
energy.loc['Republic of Korea']

我想将索引值从“Republic of Korea”更改为“South Korea”。但数据框太大了,无法更改每个索引值。我如何仅更改此单个值?


6
你的问题不够清晰,你想要改变所有 'Republic of Korea' 的实例还是想知道如何更新许多不同索引值?请提供一个典型的示例,并包含你的代码和期望的结果。此外,你可以使用 df.index.set_value(df.index, 'Republic of Korea', 'South Korea') - EdChum
9个回答

116

@EdChum的解决方案看起来不错。这里有一个使用rename的解决方案,它会替换索引中的所有这些值。

energy.rename(index={'Republic of Korea':'South Korea'},inplace=True)

这里是一个例子

>>> example = pd.DataFrame({'key1' : ['a','a','a','b','a','b'],
           'data1' : [1,2,2,3,nan,4],
           'data2' : list('abcdef')})
>>> example.set_index('key1',inplace=True)
>>> example
      data1 data2
key1             
a       1.0     a
a       2.0     b
a       2.0     c
b       3.0     d
a       NaN     e
b       4.0     f

>>> example.rename(index={'a':'c'}) # can also use inplace=True
      data1 data2
key1             
c       1.0     a
c       2.0     b
c       2.0     c
b       3.0     d
c       NaN     e
b       4.0     f

5
这应该是最佳答案。 - Francesco
这可以在多级索引的一个级别上完成吗? - HoosierDaddy
@HoosierDaddy 它可以,只需添加参数 level='key1'(将 'key1' 替换为您要更改的级别名称)。但不幸的是,我发现这非常缓慢和昂贵(在我的情况下,160k 行需要 36 秒)。其他答案中可能有更快的选项,但我不确定。 - Neil Traft
它给我返回了TypeError: 'set' object is not callable错误...(在一个具有RangeIndex(start=0, stop=1, step=1)索引的DataFrame上)。 - undefined

82

你想做这样的事情:

as_list = df.index.tolist()
idx = as_list.index('Republic of Korea')
as_list[idx] = 'South Korea'
df.index = as_list
基本上,您将索引作为列表获取,更改其中一个元素,然后替换现有索引。

2
如果一开始有索引名称,这将删除它。只需小心操作。更好的方法是使用df.index._data = np.array(as_list)来替换最后一行代码,这样只会更改索引的值,而不会影响索引的其他属性。 - Zhang18
更好的方法是,第一行不使用as_list = df.index.tolist(),而是使用as_list = df.index.values.copy()。然后,最后一行应该是df.index._data = as_list.copy()。据我所知,如果所有索引都正确设置,则与@Zhang18的评论没有任何区别,但是如果任何索引列对于某些行为空(导致NaN),并且您想保留数组的其他特性,那么就不应该使用np.array(... ),因为它们会将NaN转换为'nan'。顺便说一下,df.index.values具有dtype = object,因此您不会遇到任何字符串赋值问题。 - Hojin Cho
不确定自从这篇文章写出来以后Pandas是否有所改变,但是设置df.index._data对我来说似乎没有任何作用。它会改变._data但不会改变.values。至于直接设置index,那将完全破坏MultiIndex。最后,这个解决方案只会更改“Republic of Korea”的第一个实例,而不是所有实例。 - Neil Traft

20

试试这个

df.rename(index={'Republic of Korea':'South Korea'},inplace=True)

2
虽然这段代码可能回答了问题,但是提供关于为什么和/或如何回答问题的额外上下文可以提高其长期价值。 - xiawi
1
这应该是被选中的答案。有关此答案的更多信息,请访问https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.rename.html。 - LNI

12
如果您有多级索引DataFrame,请按照以下步骤操作:
# input DataFrame
import pandas as pd
t = pd.DataFrame(data={'i1':[0,0,0,0,1,1,1,1,2,2,2,2],
                       'i2':[0,1,2,3,0,1,2,3,0,1,2,3],
                       'x':[1.,2.,3.,4.,5.,6.,7.,8.,9.,10.,11.,12.]})
t.set_index(['i1','i2'], inplace=True)
t.sort_index(inplace=True)

# changes index level 'i1' values 0 to -1
t.rename(index={0:-1}, level='i1', inplace=True)

@Abdul Rafay的答案同样适用于多重索引。 - layser
2
FYI,排序与答案无关。答案只是最后一行。(为了帮助未来的读者。) - Neil Traft
@layser 应该注意到 @Adbul Rafay 的回答没有指定 level 关键字,如果在多级索引上使用这个关键字会非常危险。实际上,任何匹配的值都将在所有级别上被替换。 - Carmellose

9

这是另一个好方法,使用replace函数来处理列。

df.reset_index(inplace=True)
df.drop('index', axis = 1, inplace=True)
df["Country"].replace("Republic of Korea", value="South Korea", inplace=True)
df.set_index("Country", inplace=True)

5
这是另一个基于set_value的想法。
df = df.reset_index()
df.drop('index', axis = 1, inplace=True)
index = df.index[df["Country"] == "Republic of Korea"]
df.set_value(index, "Country", "South Korea")
df = df.set_index("Country")
df["Country"] = df.index

1
谢谢,set_value 就是我要找的!我之前试图使用 df.iloc[index]['Country'] = value 来设置值,但是出现了 SettingWithCopyWarning 警告,并且没有起作用。 - JD D

2
我们可以使用rename函数来更改行索引或列名。以下是一个例子,
假设数据框如下所示,
       student_id     marks
index
  1        12          33
  2        23          98
  • 将索引从1改为5

我们将使用axis = 0来代表行

df.rename({ 1 : 5 }, axis=0)

df指的是数据框变量。因此,输出将如下所示:

       student_id     marks
index
  5        12          33
  2        23          98
  • 更改列名

我们需要使用 axis = 1

df.rename({ "marks" : "student_marks" }, axis=1)

那么,修改后的数据框如下:

       student_id     student_marks
index
  5        12              33
  2        23              98

1
这似乎也可以工作:

energy.index.values[energy.index.tolist().index('Republic of Korea')] = 'South Korea'

我不知道这是否被推荐或反对。

0
如果你的DataFrame有RangeIndex(参见docs),就像这个只有一行的df一样:
>>> df.index
RangeIndex(start=0, stop=1, step=1)

>>> df.index.values
array([0])

...你可以用以下方法更改索引值:
new_index=42
df.index = pd.RangeIndex(start=new_index, stop=new_index+1, step=1)

为了达到所期望的效果:
>>> df.index
RangeIndex(start=42, stop=43, step=1)

>>> df.index.values
array([42])

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