使用索引为pandas DataFrame中的特定单元格设置值

Mit*_*tkp 396 python dataframe pandas


我已经创建了一个pandas DataFrame

df = DataFrame(index=['A','B','C'], columns=['x','y'])
Run Code Online (Sandbox Code Playgroud)

得到了这个

    x    y
A  NaN  NaN
B  NaN  NaN
C  NaN  NaN


然后我想为特定单元格赋值,例如行'C'和列'x'.我期望得到这样的结果:

    x    y
A  NaN  NaN
B  NaN  NaN
C  10  NaN

使用此代码:

df.xs('C')['x'] = 10
Run Code Online (Sandbox Code Playgroud)

但是df的内容没有改变.在数据帧中它只是Nan的.

有什么建议?

unu*_*tbu 497

RukTech的回答,df.set_value('C', 'x', 10)是远远比我以下建议的选项离开快.但是,它已被定为弃用.

展望未来,推荐的方法是.iat/.at.


为什么df.xs('C')['x']=10不起作用:

df.xs('C')默认情况下,返回带有数据副本的新数据框,所以

df.xs('C')['x']=10
Run Code Online (Sandbox Code Playgroud)

仅修改此新数据框.

df['x']返回df数据帧的视图,所以

df['x']['C'] = 10
Run Code Online (Sandbox Code Playgroud)

修改df自己.

警告:有时很难预测操作是返回副本还是视图.出于这个原因,文档建议避免使用"链式索引"进行分配.


所以建议的替代方案是

df.at['C', 'x'] = 10
Run Code Online (Sandbox Code Playgroud)

哪个修改df.


In [18]: %timeit df.set_value('C', 'x', 10)
100000 loops, best of 3: 2.9 µs per loop

In [20]: %timeit df['x']['C'] = 10
100000 loops, best of 3: 6.31 µs per loop

In [81]: %timeit df.at['C', 'x'] = 10
100000 loops, best of 3: 9.2 µs per loop
Run Code Online (Sandbox Code Playgroud)

  • 根据维护者的说法,这不是建议设置值的方法.请参阅http://stackoverflow.com/a/21287235/1579844和我的回答. (6认同)
  • @smci:`'x'`是`df`中列的名称.`df.x`返回一个`Series`,其值为'x`列.我将它改为`df ['x']`因为这个符号可以用于任何列名(与点符号不同),我认为更清楚. (3认同)

Ruk*_*ech 215

更新:.set_value方法将被弃用..iat/.at是很好的替代品,不幸的是,pandas提供的文档很少


最快的方法是使用set_value.这种方法比.set_value方法快约100倍.例如:

.iat/.at

  • 它甚至比`df ['x'] ['C'] = 10`更好. (5认同)
  • 1000个循环,最佳3:**195μs**每个循环"df ['x'] ['C'] = 10"1000个循环,最佳3:**310μs**每个循环"df.ix [ 'C','x'] = 10"1000个循环,最佳3:**189μs**每个循环"df.xs('C',copy = False)['x'] = 10"1000个循环,最佳3:**每循环7.22μs**"df.set_value('C','x',10)" (5认同)
  • 似乎已弃用https://pandas.pydata.org/pandas-docs/version/0.24/reference/api/pandas.DataFrame.set_value.html (2认同)

Bla*_*g23 82

您还可以使用条件查找,.loc如下所示:

df.loc[df[<some_column_name>] == <condition>, [<another_column_name>]] = <value_to_add>
Run Code Online (Sandbox Code Playgroud)

<some_column_name您想要检查<condition>变量的列在哪里,并且<another_column_name>是要添加到的列(可以是新列或已存在的列).<value_to_add>是要添加到该列/行的值.

此示例不能准确处理手头的问题,但对于想要根据条件添加特定值的人可能会有用.

  • 第二列需要在括号上,否则所有列都将被值覆盖.像这样:`df.loc [df ['age'] == 3,['age-group']] ='kids' (5认同)

Yar*_*riv 35

建议的方法(根据维护者)设置一个值是:

df.ix['x','C']=10
Run Code Online (Sandbox Code Playgroud)

使用"链式索引"(df['x']['C'])可能会导致问题.

看到:

  • 不推荐使用ix:http://pandas-docs.github.io/pandas-docs-travis/whatsnew.html#deprecate-ix (5认同)

小智 24

尝试使用 df.loc[row_index,col_indexer] = value

  • 欢迎来到Stack Overflow!请考虑编辑您的帖子,以添加有关您的代码的功能以及解决问题的原因的更多说明.一个主要只包含代码的答案(即使它正在工作)通常不会帮助OP理解他们的问题.如果只是猜测,也建议您不要发布答案.一个好的答案将有一个合理的理由,为什么它可以解决OP的问题. (6认同)
  • 此代码不起作用(或不再起作用?),因为它不会替换该值。 (3认同)

小智 19

这是唯一对我有用的东西!

df.loc['C', 'x'] = 10
Run Code Online (Sandbox Code Playgroud)

详细了解.loc 这里.

  • `at` 与 `loc` 类似,两者都提供基于标签的查找。如果您只需要获取或设置 DataFrame 或 Series 中的单个值,请使用“at”。来自 [padas 文档](https://pandas.pydata.org/pandas-docs/stable/ generated/pandas.DataFrame.at.html) (2认同)
  • 这不适用于数字索引和字符串索引的混合。 (2认同)

DIN*_*LIT 10

.iat/.at是很好的解决方案。假设您有一个简单的data_frame:

   A   B   C
0  1   8   4 
1  3   9   6
2  22 33  52
Run Code Online (Sandbox Code Playgroud)

如果我们要修改单元格的值,则[0,"A"]可以使用以下解决方案之一:

  1. df.iat[0,0] = 2
  2. df.at[0,'A'] = 2

这是一个完整的示例,说明如何iat用于获取和设置cell的值:

def prepossessing(df):
  for index in range(0,len(df)): 
      df.iat[index,0] = df.iat[index,0] * 2
  return df
Run Code Online (Sandbox Code Playgroud)

y_train之前:

    0
0   54
1   15
2   15
3   8
4   31
5   63
6   11
Run Code Online (Sandbox Code Playgroud)

调用预设函数后的y_train iat进行更改,以将每个单元格的值乘以2:

     0
0   108
1   30
2   30
3   16
4   62
5   126
6   22
Run Code Online (Sandbox Code Playgroud)


Ser*_*ndt 9

避免使用链式索引进行分配

您正在处理带有链式索引的分配,这将导致SettingWithCopy 警告。应尽一切努力避免这种情况。

您的作业必须求助于一个单曲.loc[].iloc[]切片,如此处所述。因此,在你的情况下:

df.loc['C', 'x'] = 10
Run Code Online (Sandbox Code Playgroud)


Goo*_*ill 8

以下是所有用户针对按整数和字符串索引的数据帧提供的有效解决方案的摘要。

df.ilocdf.loc并且df.at适用于两种类型的数据框,df.iloc仅适用于行/列整数索引,df.locdf.at支持使用列名称和/或整数索引设置值。

当指定的索引不存在时, 和df.loc都会df.at将新插入的行/列追加到现有数据框中,但df.iloc会引发"IndexError: positional indexers are out-of-bounds". 在Python 2.7和3.7中测试的工作示例如下:

import numpy as np, pandas as pd

df1 = pd.DataFrame(index=np.arange(3), columns=['x','y','z'])
df1['x'] = ['A','B','C']
df1.at[2,'y'] = 400

# rows/columns specified does not exist, appends new rows/columns to existing data frame
df1.at['D','w'] = 9000
df1.loc['E','q'] = 499

# using df[<some_column_name>] == <condition> to retrieve target rows
df1.at[df1['x']=='B', 'y'] = 10000
df1.loc[df1['x']=='B', ['z','w']] = 10000

# using a list of index to setup values
df1.iloc[[1,2,4], 2] = 9999
df1.loc[[0,'D','E'],'w'] = 7500
df1.at[[0,2,"D"],'x'] = 10
df1.at[:, ['y', 'w']] = 8000

df1
>>> df1
     x     y     z     w      q
0   10  8000   NaN  8000    NaN
1    B  8000  9999  8000    NaN
2   10  8000  9999  8000    NaN
D   10  8000   NaN  8000    NaN
E  NaN  8000  9999  8000  499.0
Run Code Online (Sandbox Code Playgroud)


小智 6

你可以使用.iloc.

df.iloc[[2], [0]] = 10
Run Code Online (Sandbox Code Playgroud)


小智 6

在我的示例中,我只是在选定的单元格中对其进行了更改

    for index, row in result.iterrows():
        if np.isnan(row['weight']):
            result.at[index, 'weight'] = 0.0
Run Code Online (Sandbox Code Playgroud)

“结果”是带有“权重”列的dataField


iva*_*ncz 6

set_value() 已弃用。

从0.23.4版本开始,Pandas“宣告未来”...

>>> df
                   Cars  Prices (U$)
0               Audi TT        120.0
1 Lamborghini Aventador        245.0
2      Chevrolet Malibu        190.0
>>> df.set_value(2, 'Prices (U$)', 240.0)
__main__:1: FutureWarning: set_value is deprecated and will be removed in a future release.
Please use .at[] or .iat[] accessors instead

                   Cars  Prices (U$)
0               Audi TT        120.0
1 Lamborghini Aventador        245.0
2      Chevrolet Malibu        240.0
Run Code Online (Sandbox Code Playgroud)

考虑到这个建议,以下是如何使用它们的演示:

  • 按行/列整数位置

>>> df.iat[1, 1] = 260.0
>>> df
                   Cars  Prices (U$)
0               Audi TT        120.0
1 Lamborghini Aventador        260.0
2      Chevrolet Malibu        240.0
Run Code Online (Sandbox Code Playgroud)
  • 按行/列标签

>>> df.at[2, "Cars"] = "Chevrolet Corvette"
>>> df
                  Cars  Prices (U$)
0               Audi TT        120.0
1 Lamborghini Aventador        260.0
2    Chevrolet Corvette        240.0
Run Code Online (Sandbox Code Playgroud)

参考:


Mil*_*uss 6

要设置值,请使用:

df.at[0, 'clm1'] = 0
Run Code Online (Sandbox Code Playgroud)
  • 推荐的最快的设置变量的方法。
  • set_valueix已弃用。
  • 没有警告,与ilocloc


Att*_*utt 6

使用条件索引的一种方法是首先获取满足条件的所有行的索引,然后以多种方式简单地使用这些行索引

conditional_index = df.loc[ df['col name'] <condition> ].index
Run Code Online (Sandbox Code Playgroud)

示例条件如下

==5, >10 , =="Any string", >= DateTime
Run Code Online (Sandbox Code Playgroud)

然后您可以通过多种方式使用这些行索引,例如

  1. 替换conditional_index的一列值
df.loc[conditional_index , [col name]]= <new value>
Run Code Online (Sandbox Code Playgroud)
  1. 替换条件索引的多列值
df.loc[conditional_index, [col1,col2]]= <new value>
Run Code Online (Sandbox Code Playgroud)
  1. 保存条件索引的一个好处是您可以将一列的值分配给具有相同行索引的另一列
df.loc[conditional_index, [col1,col2]]= df.loc[conditional_index,'col name']
Run Code Online (Sandbox Code Playgroud)

这都是可能的,因为 .index 返回一个索引数组,.loc 可以将其与直接寻址一起使用,从而避免一次又一次的遍历。


Kas*_*rGL 6

我会建议:

df.loc[index_position, "column_name"] = some_value
Run Code Online (Sandbox Code Playgroud)


pro*_*sti 5

我测试过,输出速度df.set_value稍快一些,但官方方法df.at看起来是最快的非弃用方法。

\n\n
import numpy as np\nimport pandas as pd\n\ndf = pd.DataFrame(np.random.rand(100, 100))\n\n%timeit df.iat[50,50]=50 # \xe2\x9c\x93\n%timeit df.at[50,50]=50 #  \xe2\x9c\x94\n%timeit df.set_value(50,50,50) # will deprecate\n%timeit df.iloc[50,50]=50\n%timeit df.loc[50,50]=50\n\n7.06 \xc2\xb5s \xc2\xb1 118 ns per loop (mean \xc2\xb1 std. dev. of 7 runs, 100000 loops each)\n5.52 \xc2\xb5s \xc2\xb1 64.2 ns per loop (mean \xc2\xb1 std. dev. of 7 runs, 100000 loops each)\n3.68 \xc2\xb5s \xc2\xb1 80.8 ns per loop (mean \xc2\xb1 std. dev. of 7 runs, 100000 loops each)\n98.7 \xc2\xb5s \xc2\xb1 1.07 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 10000 loops each)\n109 \xc2\xb5s \xc2\xb1 1.42 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 10000 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n\n

请注意,这是设置单个单元格的值。对于向量lociloc应该是更好的选择,因为它们是向量化的。

\n


Gon*_*ica 5

如果想将 df 位置 (0,0) 的单元格更改为字符串,例如\'"236"76"\',则以下选项可以完成工作:

\n
df[0][0] = \'"236"76"\'\n# %timeit df[0][0] = \'"236"76"\'\n# 938 \xc2\xb5s \xc2\xb1 83.4 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 1000 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n

或者使用pandas.DataFrame.at

\n
df.at[0, 0] = \'"236"76"\'\n#  %timeit df.at[0, 0] = \'"236"76"\' \n#15 \xc2\xb5s \xc2\xb1 2.09 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 100000 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n

或者使用pandas.DataFrame.iat

\n
df.iat[0, 0] = \'"236"76"\'\n#  %timeit df.iat[0, 0] = \'"236"76"\'\n# 41.1 \xc2\xb5s \xc2\xb1 3.09 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 10000 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n

或者使用pandas.DataFrame.loc

\n
df.loc[0, 0] = \'"236"76"\'\n#  %timeit df.loc[0, 0] = \'"236"76"\'\n# 5.21 ms \xc2\xb1 401 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 100 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n

或者使用pandas.DataFrame.iloc

\n
df.iloc[0, 0] = \'"236"76"\'\n#  %timeit df.iloc[0, 0] = \'"236"76"\'\n# 5.12 ms \xc2\xb1 300 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 100 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n

如果时间相关,使用pandas.DataFrame.at是最快的方法。

\n