如何在Python Pandas DataFrame中更新特定行的值?

72

在Pandas中,由于其完善的索引方法,我可以轻松地以各种方式提取数据。但是,我仍然困惑如何更改现有DataFrame中的数据。

下面的代码中,我有两个数据框,并且我的目标是从第二个数据框中的值更新第一个数据框中特定行的值。我该如何实现?

import pandas as pd
df = pd.DataFrame({'filename' :  ['test0.dat', 'test2.dat'], 
                                  'm': [12, 13], 'n' : [None, None]})
df2 = pd.DataFrame({'filename' :  'test2.dat', 'n':16}, index=[0])

# this overwrites the first row but we want to update the second
# df.update(df2)

# this does not update anything
df.loc[df.filename == 'test2.dat'].update(df2)

print(df)

提供

   filename   m     n
0  test0.dat  12  None
1  test2.dat  13  None

[2 rows x 3 columns]

但是我该如何实现这个目标:

    filename   m     n
0  test0.dat  12  None
1  test2.dat  13  16

[2 rows x 3 columns]

7个回答

83

首先,pandas使用索引进行更新。当一个更新命令没有更新任何内容时,请检查左右两侧。如果您不更新索引以遵循您的标识逻辑,则可以执行以下操作:

>>> df.loc[df.filename == 'test2.dat', 'n'] = df2[df2.filename == 'test2.dat'].loc[0]['n']
>>> df
Out[331]: 
    filename   m     n
0  test0.dat  12  None
1  test2.dat  13    16
如果您想对整个表执行此操作,我建议一种比先前提到的方法更为优越的方法:由于您的标识符是filename,请将filename设置为索引,然后按照您想要的方式使用update()。无论是merge还是apply()方法都包含不必要的开销:
>>> df.set_index('filename', inplace=True)
>>> df2.set_index('filename', inplace=True)
>>> df.update(df2)
>>> df
Out[292]: 
            m     n
filename           
test0.dat  12  None
test2.dat  13    16

目前,update()存在一些错误。它不会保留数据类型,并且可能会丢失一些数据。 - Molin.L

17
在SQL中,我会一次性完成它。
update table1 set col1 = new_value where col1 = old_value

但在Python Pandas中,我们可以这样做:

data = [['ram', 10], ['sam', 15], ['tam', 15]] 
kids = pd.DataFrame(data, columns = ['Name', 'Age']) 
kids

它将会生成以下输出:

    Name    Age
0   ram     10
1   sam     15
2   tam     15

现在我们可以运行:

kids.loc[kids.Age == 15,'Age'] = 17
kids

将显示以下输出

Name    Age
0   ram     10
1   sam     17
2   tam     17

应该等同于以下SQL查询

update kids set age = 17 where age = 15

8
如果你有一个大的数据框,只需要更新其中的几个值,我会使用apply方法进行更新,像这样:
import pandas as pd

df = pd.DataFrame({'filename' :  ['test0.dat', 'test2.dat'], 
                                  'm': [12, 13], 'n' : [None, None]})

data = {'filename' :  'test2.dat', 'n':16}

def update_vals(row, data=data):
    if row.filename == data['filename']:
        row.n = data['n']
    return row

df.apply(update_vals, axis=1)

5
这个案例无效,因为 apply 函数中的行与数据框不相关,因此它不会被更新。https://dev59.com/h1QJ5IYBdhLWcg3wKykQ - user495732 Why Me

4

将其他位置上相同的值用于更新null元素。使用函数func对列进行逐个合并,将DataFrame与另一个DataFrame组合。生成的DataFrame的行和列索引将是两者的并集。

df1 = pd.DataFrame({'A': [None, 0], 'B': [None, 4]})
df2 = pd.DataFrame({'A': [1, 1], 'B': [3, 3]})
df1.combine_first(df2)
     A    B
0  1.0  3.0
1  0.0  4.0

此链接提供更多信息


你似乎只是从combine_first的示例中简单地复制了代码。OP应该如何调整它以确保它适用于他们的目的?难道不应该由OP负责索引,以确保正确的索引被更新吗? - Teepeemm
在这种情况下,df2优先于df1。我只是复制了它,因为这是一个创建用于解决类似于这个问题的函数。 - Pablo Vilas

3

可能有几种方法可以实现这一点,但其中一种方法是在文件名/m列上将两个数据框合并,然后如果找到匹配项,则从右侧数据框中填充“n”列。 代码中的n_x,n_y指的是合并中的左/右数据框。

In[100] : df = pd.merge(df1, df2, how='left', on=['filename','m'])

In[101] : df
Out[101]: 
    filename   m   n_x  n_y
0  test0.dat  12  None  NaN
1  test2.dat  13  None   16

In[102] : df['n'] = df['n_y'].fillna(df['n_x'])

In[103] : df = df.drop(['n_x','n_y'], axis=1)

In[104] : df
Out[104]: 
    filename   m     n
0  test0.dat  12  None
1  test2.dat  13    16

1
如果您想将任何内容放在第ii行中,请添加方括号:
df.loc[df.iloc[ii].name, 'filename'] = [{'anything': 0}]

1

我需要根据同一数据框中另一列的值的条件,在几行数据框中更新并添加后缀 -

数据框具有特征和实体列,需要根据特定的特征类型更新实体。

df.loc[df.Feature == 'dnb', 'Entity'] = 'duns_' + df.loc[df.Feature == 'dnb','Entity']

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