【问题标题】:Replace value for a selected cell in pandas DataFrame without using index在不使用索引的情况下替换 pandas DataFrame 中选定单元格的值
【发布时间】:2013-07-17 18:44:18
【问题描述】:

这是一个与this question 相当相似的问题,但有一个关键区别:我不是根据索引而是根据某些标准来选择我想要更改的数据。

如果我应用的条件返回单行,我希望能够以简单的方式设置该行中某一列的值,但我的第一次尝试不起作用:

>>> d = pd.DataFrame({'year':[2008,2008,2008,2008,2009,2009,2009,2009], 
...                   'flavour':['strawberry','strawberry','banana','banana',
...                   'strawberry','strawberry','banana','banana'],
...                   'day':['sat','sun','sat','sun','sat','sun','sat','sun'],
...                   'sales':[10,12,22,23,11,13,23,24]})

>>> d
   day     flavour  sales  year
0  sat  strawberry     10  2008
1  sun  strawberry     12  2008
2  sat      banana     22  2008
3  sun      banana     23  2008
4  sat  strawberry     11  2009
5  sun  strawberry     13  2009
6  sat      banana     23  2009
7  sun      banana     24  2009

>>> d[d.sales==24]
   day flavour  sales  year
7  sun  banana     24  2009

>>> d[d.sales==24].sales = 100
>>> d
   day     flavour  sales  year
0  sat  strawberry     10  2008
1  sun  strawberry     12  2008
2  sat      banana     22  2008
3  sun      banana     23  2008
4  sat  strawberry     11  2009
5  sun  strawberry     13  2009
6  sat      banana     23  2009
7  sun      banana     24  2009

因此,与其将 2009 年周日的香蕉销量设置为 100,不如什么都没有发生!最好的方法是什么?理想情况下,解决方案应该使用行号,因为您通常不会提前知道!

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    老问题,但我很惊讶没有人提到 numpy 的 .where() 功能(可以直接从 pandas 模块调用)。

    在这种情况下,代码是:

    d.sales = pd.np.where(d.sales == 24, 100, d.sales)
    

    据我所知,这是有条件地更改系列数据的最快方法之一。

    【讨论】:

      【解决方案2】:

      不确定旧版本的 pandas,但在 0.16 中,可以根据多个列值设置特定单元格的值。

      扩展@waitingkuo提供的答案,同样的操作也可以根据多列的值来做。

      d.loc[(d.day== 'sun') & (d.flavour== 'banana') & (d.year== 2009),'sales'] = 100
      

      【讨论】:

        【解决方案3】:

        有很多方法可以做到这一点

        1

        In [7]: d.sales[d.sales==24] = 100
        
        In [8]: d
        Out[8]: 
           day     flavour  sales  year
        0  sat  strawberry     10  2008
        1  sun  strawberry     12  2008
        2  sat      banana     22  2008
        3  sun      banana     23  2008
        4  sat  strawberry     11  2009
        5  sun  strawberry     13  2009
        6  sat      banana     23  2009
        7  sun      banana    100  2009
        

        2

        In [26]: d.loc[d.sales == 12, 'sales'] = 99
        
        In [27]: d
        Out[27]: 
           day     flavour  sales  year
        0  sat  strawberry     10  2008
        1  sun  strawberry     99  2008
        2  sat      banana     22  2008
        3  sun      banana     23  2008
        4  sat  strawberry     11  2009
        5  sun  strawberry     13  2009
        6  sat      banana     23  2009
        7  sun      banana    100  2009
        

        3

        In [28]: d.sales = d.sales.replace(23, 24)
        
        In [29]: d
        Out[29]: 
           day     flavour  sales  year
        0  sat  strawberry     10  2008
        1  sun  strawberry     99  2008
        2  sat      banana     22  2008
        3  sun      banana     24  2008
        4  sat  strawberry     11  2009
        5  sun  strawberry     13  2009
        6  sat      banana     24  2009
        7  sun      banana    100  2009
        

        【讨论】:

        • 是的!解决方案 1. 有效。这有点违反直觉:d.sales[d.sales==24] = 100 但这不起作用:d[d.sales==24].sales=100。他们看起来(功能上)对我来说是一样的。呃,好吧。谢谢@waitingkuo。
        • d[d.sales==24] 生成一个新对象。
        • 重新。 @waitingkuo 的评论:熊猫人,这是预期的行为吗? d[d.sales==24] 应该生成原始 DataFrame 的副本当然不直观。事实上,我想说每个对象都应该是对原始对象的引用(包括选择一个正确地“折叠”到熊猫 Series 的单行),除非用户明确要求(通过某种 @987654330 @)。想法?
        • 仅供参考:这些现在将在 0.13 中引发/警告,请参阅(此处)[pandas.pydata.org/pandas-docs/dev/…)
        • @Jeff 如何处理这些警告,或者有没有其他正确的方法可以在没有警告的情况下做到这一点?
        猜你喜欢
        • 2012-11-30
        • 2017-10-28
        • 1970-01-01
        • 2012-03-18
        • 2016-11-30
        • 1970-01-01
        • 1970-01-01
        • 2021-09-12
        • 2021-11-08
        相关资源
        最近更新 更多