Pandas:使用行作为索引更新数据帧,但保持原始索引安全

时间:2014-09-16 18:33:56

标签: python pandas

我想知道是否有一种最快的方法来使用行作为索引来更新数据帧,但保持原始索引的安全。

我的工作方法:

df = DataFrame( { "name":  ['SEBASTIEN', 'JOHN', 'JENNY'] , "age": [39, 34, 32], "city": ['denver','chicago','los angeles'] } )
updt = DataFrame( { "firstname":  ['JOHN'] ,  "age": [42] } )

>>> df
   age         city       name
0   39       denver  SEBASTIEN
1   34      chicago       JOHN
2   32  los angeles      JENNY

df['index'] = df.index    
df.set_index('name', inplace=True)
updt.set_index('firstname', inplace=True)
df.update(updt)
df['name'] = df.index
df.set_index('index', inplace=True)

>>> df
       age         city       name
index                             
0       39       denver  SEBASTIEN
1       42      chicago       JOHN
2       32  los angeles      JENNY

非常感谢。

2 个答案:

答案 0 :(得分:2)

这是一个简单的合并和combine_first。比直接索引快得多。您也可以指定left_onright_on,而不是根据需要重命名。

In [28]: result = pd.merge(df,updt.rename(columns={'firstname' : 'name'}),on=['name'],suffixes=['_l','_r'],how='outer')

In [29]: result
Out[29]: 
   age_l         city       name  age_r
0     39       denver  SEBASTIEN    NaN
1     34      chicago       JOHN     42
2     32  los angeles      JENNY    NaN

In [31]: result['age'] = result['age_r'].combine_first(result['age_l'])

In [32]: result
Out[32]: 
   age_l         city       name  age_r  age
0     39       denver  SEBASTIEN    NaN   39
1     34      chicago       JOHN     42   42
2     32  los angeles      JENNY    NaN   32

答案 1 :(得分:0)

这完全取决于两帧的相对大小;在某些情况下,这可能足够快:

>>> i = updt['firstname'].isin(df['name'])        # updt indexer
>>> lookup = df['name'].tolist().index            # look-up function
>>> iter = map(lookup, updt.loc[i, 'firstname'])  # iterator
>>> j = np.fromiter(iter, dtype='int64')          # df indexer
>>> df.loc[j, 'age'] = updt.loc[i, 'age'].values

如果您已经知道所有i已经在firstname中,则您不需要df索引器。

或者,

>>> sorter = np.argsort(df['name'].values)
>>> i = np.searchsorted(df['name'].values[sorter], updt['firstname'])
>>> indexer = df.index[sorter[i]]
>>> df.loc[indexer, 'age'] = updt['age'].values