【问题标题】:pandas: set values with (row, col) indices熊猫:使用(行,列)索引设置值
【发布时间】:2012-08-19 11:49:03
【问题描述】:

pandas 提供通过行和列索引列表查找的能力,

In [49]: index = ['a', 'b', 'c', 'd']

In [50]: columns = ['one', 'two', 'three', 'four']

In [51]: M = pandas.DataFrame(np.random.randn(4,4), index=index, columns=columns)

In [52]: M
Out[52]: 
        one       two     three      four
a -0.785841 -0.538572  0.376594  1.316647
b  0.530288 -0.975547  1.063946 -1.049940
c -0.794447 -0.886721  1.794326 -0.714834
d -0.158371  0.069357 -1.003039 -0.807431

In [53]: M.lookup(index, columns) # diagonal entries
Out[53]: array([-0.78584142, -0.97554698,  1.79432641, -0.8074308 ])

我想使用同样的索引方法来设置M 的元素。我该怎么做?

【问题讨论】:

标签: python pandas


【解决方案1】:

自从写下这个答案以来已经过去了很多年,所以我虽然可能会做出一点贡献。随着 pandas 的重构,尝试在一个位置设置一个值

M.iloc[index][col]

可能会警告您尝试在切片中设置值。

SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy

在 0.21 之后的 pandas 版本中,正确的“pythonic”方式现在是 pandas.DataFrame.at operator

看起来像这样:

M.at[index,col] = new_value

旧版本的答案: 在旧版本中更“pythonic”的方法是使用pandas.DataFrame.set_value 指令。请注意,此指令返回结果 DataFrame。

M.set_value(index,column,new_value)

我只是想在弄清楚 .iloc 或 .ix 方法可能产生的警告的来源之后将其发布在这里。

set_value 方法也适用于多索引数据帧,方法是将索引的多个级别作为元组放入(例如,用 (col,subcol) 替换列)

【讨论】:

  • 感谢您发布此内容,今天我在一所主要大学的数据科学课上的“教授”告诉我,最好复制并操作整个数据帧列,而不是“一次修改一个值” " (with apply)——前一个选项无论如何都会这样做!这个答案有一个真正的教育,一个人无法支付哈哈。您提供的链接很棒:pandas.pydata.org/pandas-docs/stable/… 也离题但有趣的是pandas.pydata.org/pandas-docs/stable/gotchas.html
  • set_value 自 0.21.0 版起已弃用:请改用 .at[] 或 .iat[] 访问器。 pandas Documentation
  • @JimLohse - 谢谢,更新了主要答案,因为似乎人们仍然可以找到该页面。
  • 关于使用.loc()产生的SettingWithCopyWarning。据我了解,当您打算覆盖原始 DataFrame 时,可以放心地忽略它。请参阅this thread 了解更多信息。
【解决方案2】:

我不确定我是否关注你,但你是否使用DataFrame.ix 来选择/设置单个元素:

In [79]: M
Out[79]: 
        one       two     three      four
a -0.277981  1.500188 -0.876751 -0.389292
b -0.705835  0.108890 -1.502786 -0.302773
c  0.880042 -0.056620 -0.550164 -0.409458
d  0.704202  0.619031  0.274018 -1.755726

In [75]: M.ix[0]
Out[75]: 
one     -0.277981
two      1.500188
three   -0.876751
four    -0.389292
Name: a

In [78]: M.ix[0,0]
Out[78]: -0.27798082190723405

In [81]: M.ix[0,0] = 1.0

In [82]: M
Out[82]: 
        one       two     three      four
a  1.000000  1.500188 -0.876751 -0.389292
b -0.705835  0.108890 -1.502786 -0.302773
c  0.880042 -0.056620 -0.550164 -0.409458
d  0.704202  0.619031  0.274018 -1.755726

In [84]: M.ix[(0,1),(0,1)] = 1

In [85]: M
Out[85]: 
        one       two     three      four
a  1.000000  1.000000 -0.876751 -0.389292
b  1.000000  1.000000 -1.502786 -0.302773
c  0.880042 -0.056620 -0.550164 -0.409458
d  0.704202  0.619031  0.274018 -1.755726

您还可以按索引切片:

In [98]: M.ix["a":"c","one"] = 2.0

In [99]: M
Out[99]: 
        one       two     three      four
a  2.000000  1.000000 -0.876751 -0.389292
b  2.000000  1.000000 -1.502786 -0.302773
c  2.000000 -0.056620 -0.550164 -0.409458
d  0.704202  0.619031  0.274018 -1.755726

【讨论】:

  • 这将设置单个元素,但是给定一个(行、索引、值)对的列表,有没有简单的方法一次设置它们?
  • 我认为没有,您需要遍历(行、索引、值)元组并一一设置值。如果您有三个列表 index_labels、column_labels、values,这看起来像是 M.set_value => M.set_value(index_labels, column_labels, values) 的 todo 扩展。其他选择是使用 M.update(),但这里你需要先构造一个不同的框架。
  • 您可以将元组/列表传递给 ix() 以在数据框中设置值。请参阅上面的编辑。例如 M.ix[(0,1),(0,1)] = 1
  • 这是一个非常有用的知识(我来这里只是想弄清楚如何去做!),但不幸的是,我无法像最初希望的那样设置值。谢谢!
  • Starting in 0.20.0, the .ix indexer is deprecated, in favor of the more strict .iloc and .loc indexers. ix-indexer-is-deprecated
猜你喜欢
  • 1970-01-01
  • 2016-06-29
  • 2021-10-10
  • 2017-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-07
相关资源
最近更新 更多