我创建了Pandas DataFrame

df = DataFrame(index=['A','B','C'], columns=['x','y'])


并得到了这个

    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


,但df的内容未更改。再次只是DataFrame中的NaN

有什么建议吗?

评论

不要使用“链接索引”(df ['x'] ['C']),请使用df.ix ['x','C']。

索引访问的顺序必须是:dataframe [column(系列)] [row(系列索引)],而许多人(包括我自己)更习惯于dataframe [row] [column]顺序。作为Matlab和R程序员,后者对我来说感觉更直观,但这显然不是Pandas的工作方式。.

我试过了,但最终我添加了另一个行名x和另一个列名C。您必须先执行该行,然后再执行该列。所以df.ix ['C','x'] = 10

@Yariv的评论。警告:从0.20.0开始,不建议使用.ix索引器,而建议使用更严格的.iloc和.loc索引器。 pandas.pydata.org/pandas-docs/stable/genic / ...。 df.at看起来像在粘住。

#1 楼

RukTech的答案df.set_value('C', 'x', 10)远远快于我在下面建议的选项。但是,它已被淘汰。

继续,推荐的方法是.iat/.at


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

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

df.xs('C')['x']=10


仅修改此新数据框。

df['x']返回df数据帧的视图,因此

df['x']['C'] = 10


修改df本身。

警告:有时很难预测操作是否返回副本或视图。因此,文档建议避免使用“链接索引”进行赋值。


所以推荐的替代方法是

df.at['C', 'x'] = 10


,它可以修改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


评论


API中没有df.x这样的东西。你什么意思?

–smci
13年5月20日在2:21



@smci:“ x”是df中的列名。 df.x返回带有列x中值的Series。我将其更改为df ['x'],因为此表示法适用于任何列名(与点表示法不同),而且我认为更清晰。

–unutbu
13年5月20日在11:58

我知道,我以为您是在说df.x和df.xs,df.ix一起是未知的新方法

–smci
13年5月20日在23:27

df.xs(...,copy = True)返回一个副本,这是默认行为。 df.xs(...,copy = False)返回原始值。

–smci
13年5月20日在23:28

据维护人员说,这不是建议的设置值的方法。看到stackoverflow.com/a/21287235/1579844和我的答案。

– Yariv
2014年1月22日15:45



#2 楼

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


最快的方法是使用set_value。该方法比.ix方法快100倍。例如:

df.set_value('C', 'x', 10)

评论


它甚至比df ['x'] ['C'] = 10还要好。

– ALH
15-10-17在13:16



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)”

–propjk007
16年1月12日在17:37



这对于向数据帧添加新行/列也起作用吗?

–st.ph.n
16年2月24日在18:46

是的(熊猫0.16.2)

– RukTech
16 Mar 2 '16 at 0:33

不推荐使用

–军队
19年5月7日下午4:40

#3 楼

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

df.loc[df[<some_column_name>] == <condition>, [<another_column_name>]] = <value_to_add>


其中<some_column_name是您要检查<condition>变量的列,而<another_column_name>是想要的列添加到(可以是新列,也可以是已经存在的列)。 <value_to_add>是您想要添加到该列/行的值。条件。

评论


第二列必须放在方括号中,否则所有列都将被值覆盖。像这样:df.loc [df ['age'] == 3,['age-group']] ='幼儿'

– Piizei
18/09/12在10:55



是我的索引(例如,unixtime索引)并且我试图添加尚未退出的时间戳(即新的时间戳读数)时,我无法使用此功能。有什么想法吗?

–耶拉阿布罗辛
19年6月14日在20:43

是否可以根据索引和单元格值更改值?

– BND
1月8日10:59



@BND我不确定,但是您可以解决这个明显的陷阱,而只是将索引列与另一个具有相同值的列复制?简短的答案是我不知道。

– Blairg23
1月17日23:58

@yeliabsalohcin参见以上答案。

– Blairg23
1月17日23:59

#4 楼

推荐的方法(根据维护人员)是:

df.ix['x','C']=10


使用“链接索引”(df['x']['C'])可能会导致问题。

请参阅:


https://stackoverflow.com/a/21287235/1579844
http://pandas.pydata.org/pandas-docs/dev/ indexing.html#indexing-view-versus-copy
https://github.com/pydata/pandas/pull/6031


评论


ix已弃用:pandas-docs.github.io/pandas-docs-travis/…

–ecoe
18年11月14日在21:27

完美的作品!尽管有时会弃用!

– Pavlos Ponos
5月29日6:59

#5 楼

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

评论


欢迎使用Stack Overflow!请考虑编辑您的文章,以添加更多有关代码功能以及为什么它可以解决问题的解释。通常只包含代码(即使它在起作用)的答案通常不会帮助OP理解他们的问题。如果只是猜测,也建议您不要发布答案。一个好的答案将有一个合理的理由来说明为什么它可以解决OP的问题。

–SuperBiasedMan
15年10月15日在16:46

#6 楼

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

df.loc['C', 'x'] = 10


在此处了解有关.loc的更多信息。

评论


.loc是否替换了.iat / .at?

–加百利博览会
18年7月17日在22:48

与loc类似,两者都提供基于标签的查找。如果仅需要获取或设置DataFrame或Series中的单个值,请使用at。来自padas doc

– Rutrus
18年7月31日在1:31

当我的索引元素为数字时,这对我有用。

–克里斯托弗·约翰(Christopher John)
19-2-25在8:13



这不适用于数字索引和字符串索引的混合。

– Seanny123
19 Mar 26 '19在17:21

#7 楼

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

   A   B   C
0  1   8   4 
1  3   9   6
2  22 33  52


如果我们要修改单元格的值[0,"A"]您可以使用这些解决方案:


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

这是一个完整的示例,说明如何使用iat获取并设置像元的值:

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

之前的y_train:

    0
0   54
1   15
2   15
3   8
4   31
5   63
6   11

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

     0
0   108
1   30
2   30
3   16
4   62
5   126
6   22


#8 楼

要设置值,请使用:

df.at[0, 'clm1'] = 0



建议的最快设置变量方法。

set_valueix已弃用。
没有警告,与ilocloc不同



评论


我得出了完全相同的结论。

–prosti
19年5月7日14:07



#9 楼

您可以使用.iloc

 df.iloc[[2], [0]] = 10
 


评论


此方法似乎不支持多个值,例如df.iloc [[2:8],[0]] = [2,3,4,5,6,7]是方法df.loc()本地执行的。

–strpeter
17年11月23日在10:58

#10 楼

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

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


'result'是带有列'weight'的dataField

#11 楼





从版本0.23.4开始,熊猫“宣布未来” ...

>>> 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


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


按行/列整数位置


>>> 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



按行/列标签


>>> 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


参考文献:


pandas.DataFrame.iat
pandas.DataFrame.at


#12 楼

我测试过,输出是df.set_value有点快,但是官方方法df.at看起来是最快的不推荐使用的方法。

import numpy as np
import pandas as pd

df = pd.DataFrame(np.random.rand(100, 100))

%timeit df.iat[50,50]=50 # ✓
%timeit df.at[50,50]=50 #  ✔
%timeit df.set_value(50,50,50) # will deprecate
%timeit df.iloc[50,50]=50
%timeit df.loc[50,50]=50

7.06 µs ± 118 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
5.52 µs ± 64.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
3.68 µs ± 80.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
98.7 µs ± 1.07 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
109 µs ± 1.42 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)


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

#13 楼

这是所有用户提供的针对用整数和字符串索引的数据帧的有效解决方案的摘要。 .iloc仅适用于行/列整数索引,df.loc和df.at支持使用列名和/或整数索引设置值。 loc和df.at会将新插入的行/列追加到现有数据框中,但是df.iloc会引发“ IndexError:位置索引器超出范围”。在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


#14 楼

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

conditional_index = df.loc[ df['col name'] <condition> ].index


示例条件就像

==5, >10 , =="Any string", >= DateTime


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


条件索引

df.loc[conditional_index , [col name]]= <new value>



替换条件索引的多列值

df.loc[conditional_index, [col1,col2]]= <new value>



保存conditional_index的一个好处是,您可以将一列的值分配给具有相同行索引的另一列

df.loc[conditional_index, [col1,col2]]= df.loc[conditional_index,'col name']


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

评论


那换行呢?

–FabioSpaghetti
19/12/20在9:15

只需使用df.loc [conditional_index,] = <新值>它将替换满足条件的行的所有列中的新值

–艾塔·朱特(Atta Jutt)
1月8日9:16

#15 楼

df.loc['c','x']=10
这将更改cth行和
xth列的值。

#16 楼

我建议:
df.loc[index_position, "column_name"] = some_value


#17 楼

除上述答案外,这是一个基准,比较了将数据行添加到现有数据框的不同方法。它表明对于大型数据框(至少在这些测试条件下),使用at或set-value是最有效的方法。


为每一行创建新的数据框并... />

...附加它(13.0 s)
...串联它(13.1 s)


将所有新行存储在另一个首先将容器转换为新数据框并追加...


容器=列表列表(2.0 s)
容器=列表字典(1.9 s)


预分配整个数据帧,遍历新行和所有列,并使用(


...(0.6 s)
...进行填充。 set_value(0.4 s)




对于该测试,使用了包含100,000行和1,000列以及随机numpy值的现有数据框。向此数据框添加了100个新行。

代码见下:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Nov 21 16:38:46 2018

@author: gebbissimo
"""

import pandas as pd
import numpy as np
import time

NUM_ROWS = 100000
NUM_COLS = 1000
data = np.random.rand(NUM_ROWS,NUM_COLS)
df = pd.DataFrame(data)

NUM_ROWS_NEW = 100
data_tot = np.random.rand(NUM_ROWS + NUM_ROWS_NEW,NUM_COLS)
df_tot = pd.DataFrame(data_tot)

DATA_NEW = np.random.rand(1,NUM_COLS)


#%% FUNCTIONS

# create and append
def create_and_append(df):
    for i in range(NUM_ROWS_NEW):
        df_new = pd.DataFrame(DATA_NEW)
        df = df.append(df_new)
    return df

# create and concatenate
def create_and_concat(df):
    for i in range(NUM_ROWS_NEW):
        df_new = pd.DataFrame(DATA_NEW)
        df = pd.concat((df, df_new))
    return df


# store as dict and 
def store_as_list(df):
    lst = [[] for i in range(NUM_ROWS_NEW)]
    for i in range(NUM_ROWS_NEW):
        for j in range(NUM_COLS):
            lst[i].append(DATA_NEW[0,j])
    df_new = pd.DataFrame(lst)
    df_tot = df.append(df_new)
    return df_tot

# store as dict and 
def store_as_dict(df):
    dct = {}
    for j in range(NUM_COLS):
        dct[j] = []
        for i in range(NUM_ROWS_NEW):
            dct[j].append(DATA_NEW[0,j])
    df_new = pd.DataFrame(dct)
    df_tot = df.append(df_new)
    return df_tot




# preallocate and fill using .at
def fill_using_at(df):
    for i in range(NUM_ROWS_NEW):
        for j in range(NUM_COLS):
            #print("i,j={},{}".format(i,j))
            df.at[NUM_ROWS+i,j] = DATA_NEW[0,j]
    return df


# preallocate and fill using .at
def fill_using_set(df):
    for i in range(NUM_ROWS_NEW):
        for j in range(NUM_COLS):
            #print("i,j={},{}".format(i,j))
            df.set_value(NUM_ROWS+i,j,DATA_NEW[0,j])
    return df


#%% TESTS
t0 = time.time()    
create_and_append(df)
t1 = time.time()
print('Needed {} seconds'.format(t1-t0))

t0 = time.time()    
create_and_concat(df)
t1 = time.time()
print('Needed {} seconds'.format(t1-t0))

t0 = time.time()    
store_as_list(df)
t1 = time.time()
print('Needed {} seconds'.format(t1-t0))

t0 = time.time()    
store_as_dict(df)
t1 = time.time()
print('Needed {} seconds'.format(t1-t0))

t0 = time.time()    
fill_using_at(df_tot)
t1 = time.time()
print('Needed {} seconds'.format(t1-t0))

t0 = time.time()    
fill_using_set(df_tot)
t1 = time.time()
print('Needed {} seconds'.format(t1-t0))


#18 楼

如此,您的问题是将['x',C]处的NaN转换为值10
答案是..

#19 楼

如果您不想更改整个行的值,而只更改某些列的值:

x = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
x.iloc[1] = dict(A=10, B=-10)


#20 楼

从0.21.1版开始,您还可以使用.at方法。与此处提到的.loc相比,存在一些差异-熊猫.at和.loc,但是在替换单个值时更快。

#21 楼

我也在寻找这个主题,并且提出了一种方法来遍历DataFrame并使用来自第二个DataFrame的查找值对其进行更新。这是我的代码。

src_df = pd.read_sql_query(src_sql,src_connection)
for index1, row1 in src_df.iterrows():
    for index, row in vertical_df.iterrows():
        src_df.set_value(index=index1,col=u'etl_load_key',value=etl_load_key)
        if (row1[u'src_id'] == row['SRC_ID']) is True:
            src_df.set_value(index=index1,col=u'vertical',value=row['VERTICAL'])