在不使用索引的情况下替换 pandas DataFrame 中选定单元格的值
Posted
技术标签:
【中文标题】在不使用索引的情况下替换 pandas DataFrame 中选定单元格的值【英文标题】:Replace value for a selected cell in pandas DataFrame without using index 【发布时间】: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,不如什么都没有发生!最好的方法是什么?理想情况下,解决方案应该使用行号,因为您通常不会提前知道!
【问题讨论】:
【参考方案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 如何处理这些警告,或者有没有其他正确的方法可以在没有警告的情况下做到这一点?以上是关于在不使用索引的情况下替换 pandas DataFrame 中选定单元格的值的主要内容,如果未能解决你的问题,请参考以下文章
PySpark DataFrames - 在不转换为 Pandas 的情况下进行枚举的方法?