我有一个DataFrame
df 和一个dict
d,如下所示:
>>> df
a b
0 5 10
1 6 11
2 7 12
3 8 13
4 9 14
>>> d = {6: 22, 8: 26}
对于(key, val)
字典中的每一个,我想找到列a
与键匹配的行,并用值覆盖它的b
列。例如,在这种特殊情况下,b
第 1 行的值将更改为 22,第 3 行的值将更改为 26。
我该怎么做?
假设可以将新值传播到列匹配的所有行a
(如果 column 中有重复项a
),则:
for a_val, b_val in d.iteritems():
df['b'][df.a==a_val] = b_val
或避免链接赋值操作:
for a_val, b_val in d.iteritems():
df.loc[df.a==a_val, 'b'] = b_val
请注意,要使用loc
您必须使用 Pandas 0.11 或更高版本。对于较旧的版本,您可能可以使用.ix
来防止链式分配。
@Jeff 指向此链接,该链接讨论了我在此评论中已经提到的一种现象。请注意,这不是正确性问题,因为颠倒访问顺序具有可预测的效果。您可以很容易地看到这一点,例如:
In [102]: id(df[df.a==5]['b'])
Out[102]: 113795992
In [103]: id(df['b'][df.a==5])
Out[103]: 113725760
如果您先获取列,然后根据索引分配到该列,则更改会影响该列。由于该列是 DataFrame 的一部分,因此更改会影响 DataFrame。如果您首先索引一组行,您现在不再谈论相同的 DataFrame,因此从过滤对象中获取列不会让您看到原始列。
@Jeff 建议这使它“不正确”,而我的观点是这是显而易见的预期行为。在特殊情况下,当您有一个混合数据类型列并且正在进行某些类型提升/降级时会阻止 Pandas 将值写入该列,那么您可能会遇到正确性问题。但鉴于loc
直到 Pandas 0.11 才可用,我认为指出如何通过链式赋值来做到这一点仍然是公平的,而不是假装喜欢loc
是唯一可能是正确选择的事情。
如果有人可以提供更明确的理由认为它是“不正确的”(而不是在文体上不喜欢这个),请贡献,我将尝试对各种陷阱进行更全面的描述。